LCOV - code coverage report
Current view: top level - src - ec_external.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:8ebf9ad) Lines: 83.4 % 331 276
Test Date: 2026-01-22 06:43:13 Functions: 85.7 % 7 6

            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 Routines for an external energy correction on top of a Kohn-Sham calculation
      10              : !> \par History
      11              : !>       10.2024 created
      12              : !> \author JGH
      13              : ! **************************************************************************************************
      14              : MODULE ec_external
      15              :    USE cell_types,                      ONLY: cell_type
      16              :    USE cp_control_types,                ONLY: dft_control_type
      17              :    USE cp_dbcsr_api,                    ONLY: dbcsr_copy,&
      18              :                                               dbcsr_create,&
      19              :                                               dbcsr_p_type,&
      20              :                                               dbcsr_set,&
      21              :                                               dbcsr_type,&
      22              :                                               dbcsr_type_symmetric
      23              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      24              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      25              :                                               cp_dbcsr_plus_fm_fm_t,&
      26              :                                               cp_dbcsr_sm_fm_multiply,&
      27              :                                               dbcsr_allocate_matrix_set,&
      28              :                                               dbcsr_deallocate_matrix_set
      29              :    USE cp_files,                        ONLY: close_file,&
      30              :                                               open_file
      31              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      32              :                                               cp_fm_struct_release,&
      33              :                                               cp_fm_struct_type
      34              :    USE cp_fm_types,                     ONLY: &
      35              :         cp_fm_create, cp_fm_get_diag, cp_fm_get_info, cp_fm_get_submatrix, cp_fm_maxabsval, &
      36              :         cp_fm_release, cp_fm_set_all, cp_fm_to_fm, cp_fm_type
      37              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      38              :                                               cp_logger_get_default_unit_nr,&
      39              :                                               cp_logger_type
      40              :    USE ec_env_types,                    ONLY: energy_correction_type
      41              :    USE kinds,                           ONLY: default_string_length,&
      42              :                                               dp
      43              :    USE mathlib,                         ONLY: det_3x3
      44              :    USE message_passing,                 ONLY: mp_para_env_type
      45              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      46              :    USE physcon,                         ONLY: pascal
      47              :    USE qs_core_energies,                ONLY: calculate_ptrace
      48              :    USE qs_core_matrices,                ONLY: core_matrices,&
      49              :                                               kinetic_energy_matrix
      50              :    USE qs_environment_types,            ONLY: get_qs_env,&
      51              :                                               qs_environment_type
      52              :    USE qs_force_types,                  ONLY: qs_force_type
      53              :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      54              :    USE qs_mo_types,                     ONLY: deallocate_mo_set,&
      55              :                                               get_mo_set,&
      56              :                                               mo_set_type
      57              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      58              :    USE qs_overlap,                      ONLY: build_overlap_matrix
      59              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      60              :                                               qs_rho_type
      61              :    USE trexio_utils,                    ONLY: read_trexio
      62              :    USE virial_methods,                  ONLY: one_third_sum_diag
      63              :    USE virial_types,                    ONLY: virial_type
      64              : #include "./base/base_uses.f90"
      65              : 
      66              :    IMPLICIT NONE
      67              : 
      68              :    PRIVATE
      69              : 
      70              : ! *** Global parameters ***
      71              : 
      72              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ec_external'
      73              : 
      74              :    PUBLIC :: ec_ext_energy, matrix_r_forces
      75              : 
      76              : CONTAINS
      77              : 
      78              : ! **************************************************************************************************
      79              : !> \brief External energy method
      80              : !> \param qs_env ...
      81              : !> \param ec_env ...
      82              : !> \param calculate_forces ...
      83              : !> \par History
      84              : !>       10.2024 created
      85              : !> \author JGH
      86              : ! **************************************************************************************************
      87           48 :    SUBROUTINE ec_ext_energy(qs_env, ec_env, calculate_forces)
      88              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      89              :       TYPE(energy_correction_type), POINTER              :: ec_env
      90              :       LOGICAL, INTENT(IN)                                :: calculate_forces
      91              : 
      92              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'ec_ext_energy'
      93              : 
      94              :       INTEGER                                            :: funit, handle, ia, ispin, iter, nao, &
      95              :                                                             nocc, ns, nsample, nspins, unit_nr
      96           48 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: state
      97              :       REAL(KIND=dp)                                      :: focc
      98           48 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: hmat, hnum, rnum
      99              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct, h_struct
     100              :       TYPE(cp_fm_type)                                   :: h_fm
     101           48 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: cpmos, mo_occ, mo_ref
     102              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     103              :       TYPE(cp_logger_type), POINTER                      :: logger
     104           48 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     105              :       TYPE(dft_control_type), POINTER                    :: dft_control
     106           48 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     107              : 
     108           48 :       CALL timeset(routineN, handle)
     109              : 
     110           48 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     111           48 :       nspins = dft_control%nspins
     112              : 
     113           48 :       logger => cp_get_default_logger()
     114           48 :       IF (logger%para_env%is_source()) THEN
     115           24 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     116              :       ELSE
     117           24 :          unit_nr = -1
     118              :       END IF
     119              : 
     120           48 :       ec_env%etotal = 0.0_dp
     121           48 :       ec_env%ex = 0.0_dp
     122           48 :       ec_env%exc = 0.0_dp
     123           48 :       ec_env%ehartree = 0.0_dp
     124              : 
     125           48 :       CALL get_qs_env(qs_env, mos=mos)
     126          384 :       ALLOCATE (cpmos(nspins), mo_ref(nspins), mo_occ(nspins))
     127              : 
     128           48 :       CALL cp_fm_release(ec_env%mo_occ)
     129           48 :       CALL cp_fm_release(ec_env%cpmos)
     130           48 :       IF (ec_env%debug_external) THEN
     131              :          !
     132           96 :          DO ispin = 1, nspins
     133           48 :             CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, homo=nocc)
     134           48 :             NULLIFY (fm_struct)
     135              :             CALL cp_fm_struct_create(fm_struct, ncol_global=nocc, &
     136           48 :                                      template_fmstruct=mo_coeff%matrix_struct)
     137           48 :             CALL cp_fm_create(cpmos(ispin), fm_struct)
     138           48 :             CALL cp_fm_set_all(cpmos(ispin), 0.0_dp)
     139           48 :             CALL cp_fm_create(mo_ref(ispin), fm_struct)
     140           48 :             CALL cp_fm_set_all(mo_ref(ispin), 0.0_dp)
     141           48 :             CALL cp_fm_create(mo_occ(ispin), fm_struct)
     142           48 :             CALL cp_fm_to_fm(mo_coeff, mo_occ(ispin), nocc)
     143          144 :             CALL cp_fm_struct_release(fm_struct)
     144              :          END DO
     145              :          !
     146           48 :          ec_env%mo_occ => mo_ref
     147           48 :          CALL ec_ext_debug(qs_env, ec_env, calculate_forces, unit_nr)
     148              :          !
     149           48 :          IF (ec_env%do_error) THEN
     150            4 :             CALL cp_fm_get_info(cpmos(1), nrow_global=nao)
     151              :             CALL cp_fm_struct_create(h_struct, nrow_global=nao, ncol_global=nao, &
     152            4 :                                      template_fmstruct=cpmos(1)%matrix_struct)
     153            4 :             CALL cp_fm_create(h_fm, h_struct)
     154            4 :             CALL copy_dbcsr_to_fm(ec_env%matrix_h(1, 1)%matrix, h_fm)
     155            4 :             CALL cp_fm_struct_release(h_struct)
     156           16 :             ALLOCATE (hmat(nao, nao))
     157            4 :             CALL cp_fm_get_submatrix(h_fm, hmat, 1, 1, nao, nao)
     158            4 :             CALL cp_fm_release(h_fm)
     159            4 :             IF (unit_nr > 1) THEN
     160            2 :                nsample = 5
     161              :                WRITE (unit_nr, '(/,T2,A)') &
     162            2 :                   " Write EXTERNAL Response Error file: "//TRIM(ec_env%exresperr_fn)
     163            2 :                WRITE (unit_nr, '(T2,A,I6)') " Number of Error samples is: ", nsample
     164              :                CALL open_file(ec_env%exresperr_fn, file_status="REPLACE", file_action="WRITE", &
     165            2 :                               file_form="FORMATTED", unit_number=funit)
     166           10 :                ALLOCATE (rnum(nao, nao), hnum(nao, nao))
     167            2 :                WRITE (funit, '(A)') " CP2K "
     168            2 :                WRITE (funit, *) nsample
     169            2 :                CALL RANDOM_SEED(size=ns)
     170            6 :                ALLOCATE (state(ns))
     171           18 :                DO ia = 1, ns
     172           18 :                   state(ia) = NINT(271808156._dp*SIN(5.357_dp*ia))
     173              :                END DO
     174            2 :                CALL RANDOM_SEED(put=state)
     175            2 :                CALL RANDOM_NUMBER(rnum)
     176           12 :                DO iter = 1, nsample
     177           22 :                   DO ispin = 1, nspins
     178           10 :                      WRITE (funit, *) nao, nao
     179           10 :                      CALL RANDOM_NUMBER(rnum)
     180         5530 :                      hnum(1:nao, 1:nao) = rnum(1:nao, 1:nao) + TRANSPOSE(rnum(1:nao, 1:nao))
     181         5530 :                      hnum(1:nao, 1:nao) = (hnum(1:nao, 1:nao) - 1.0_dp)*1.0E-3_dp
     182         5530 :                      rnum(1:nao, 1:nao) = hnum(1:nao, 1:nao) + hmat(1:nao, 1:nao)
     183          250 :                      DO ia = 1, nao
     184          240 :                         WRITE (funit, *) rnum(ia, 1:nao)
     185              :                      END DO
     186              :                   END DO
     187              :                END DO
     188            2 :                DEALLOCATE (rnum, hnum, state)
     189            2 :                CALL close_file(funit)
     190              :             END IF
     191           12 :             DEALLOCATE (hmat)
     192              :          END IF
     193              :          !
     194           48 :          IF (calculate_forces) THEN
     195           14 :             focc = 2.0_dp
     196           14 :             IF (nspins == 1) focc = 4.0_dp
     197           28 :             DO ispin = 1, nspins
     198           14 :                CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, homo=nocc)
     199              :                CALL cp_dbcsr_sm_fm_multiply(ec_env%matrix_h(1, 1)%matrix, ec_env%mo_occ(ispin), &
     200              :                                             cpmos(ispin), nocc, &
     201           28 :                                             alpha=focc, beta=0.0_dp)
     202              :             END DO
     203              :          END IF
     204           48 :          ec_env%cpmos => cpmos
     205              :       ELSE
     206            0 :          DO ispin = 1, nspins
     207            0 :             CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, homo=nocc)
     208            0 :             NULLIFY (fm_struct)
     209              :             CALL cp_fm_struct_create(fm_struct, ncol_global=nocc, &
     210            0 :                                      template_fmstruct=mo_coeff%matrix_struct)
     211            0 :             CALL cp_fm_create(cpmos(ispin), fm_struct)
     212            0 :             CALL cp_fm_set_all(cpmos(ispin), 0.0_dp)
     213            0 :             CALL cp_fm_create(mo_occ(ispin), fm_struct)
     214            0 :             CALL cp_fm_to_fm(mo_coeff, mo_occ(ispin), nocc)
     215            0 :             CALL cp_fm_create(mo_ref(ispin), fm_struct)
     216            0 :             CALL cp_fm_set_all(mo_ref(ispin), 0.0_dp)
     217            0 :             CALL cp_fm_struct_release(fm_struct)
     218              :          END DO
     219              : 
     220              :          ! get external information
     221            0 :          CALL ec_ext_interface(qs_env, ec_env%exresp_fn, mo_occ, mo_ref, cpmos, calculate_forces, unit_nr)
     222            0 :          ec_env%mo_occ => mo_ref
     223            0 :          ec_env%cpmos => cpmos
     224              :       END IF
     225              : 
     226           48 :       IF (calculate_forces) THEN
     227              :          ! check for orbital rotations
     228           14 :          CALL get_qs_env(qs_env, matrix_s=matrix_s)
     229           28 :          DO ispin = 1, nspins
     230              :             CALL align_vectors(ec_env%cpmos(ispin), ec_env%mo_occ(ispin), mo_occ(ispin), &
     231           28 :                                matrix_s(1)%matrix, ec_env%orbrot_index, ec_env%phase_index, unit_nr)
     232              :          END DO
     233              :          ! set up matrices for response
     234           14 :          CALL ec_ext_setup(qs_env, ec_env, .TRUE., unit_nr)
     235              :       ELSE
     236           34 :          CALL ec_ext_setup(qs_env, ec_env, .FALSE., unit_nr)
     237              :       END IF
     238              : 
     239           48 :       CALL cp_fm_release(mo_occ)
     240              : 
     241           48 :       CALL timestop(handle)
     242              : 
     243           96 :    END SUBROUTINE ec_ext_energy
     244              : 
     245              : ! **************************************************************************************************
     246              : 
     247              : ! **************************************************************************************************
     248              : !> \brief ...
     249              : !> \param qs_env ...
     250              : !> \param trexio_fn ...
     251              : !> \param mo_occ ...
     252              : !> \param mo_ref ...
     253              : !> \param cpmos ...
     254              : !> \param calculate_forces ...
     255              : !> \param unit_nr ...
     256              : ! **************************************************************************************************
     257            0 :    SUBROUTINE ec_ext_interface(qs_env, trexio_fn, mo_occ, mo_ref, cpmos, calculate_forces, unit_nr)
     258              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     259              :       CHARACTER(LEN=*)                                   :: trexio_fn
     260              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mo_occ, mo_ref, cpmos
     261              :       LOGICAL, INTENT(IN)                                :: calculate_forces
     262              :       INTEGER, INTENT(IN)                                :: unit_nr
     263              : 
     264              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'ec_ext_interface'
     265              : 
     266              :       INTEGER                                            :: handle, ispin, nao, nmos, nocc(2), nspins
     267              :       REAL(KIND=dp)                                      :: focc
     268              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     269            0 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: energy_derivative
     270              :       TYPE(dft_control_type), POINTER                    :: dft_control
     271            0 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos_trexio
     272              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     273              : 
     274            0 :       CALL timeset(routineN, handle)
     275              : 
     276            0 :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, para_env=para_env)
     277              : 
     278            0 :       nspins = dft_control%nspins
     279            0 :       nocc = 0
     280            0 :       DO ispin = 1, nspins
     281            0 :          CALL cp_fm_get_info(mo_occ(ispin), nrow_global=nao, ncol_global=nocc(ispin))
     282              :       END DO
     283              : 
     284            0 :       IF (unit_nr > 0) THEN
     285            0 :          WRITE (unit_nr, '(T2,A)') " Read EXTERNAL Response from file: "//TRIM(trexio_fn)
     286              :       END IF
     287            0 :       ALLOCATE (mos_trexio(nspins))
     288            0 :       IF (calculate_forces) THEN
     289            0 :          NULLIFY (energy_derivative)
     290            0 :          CALL dbcsr_allocate_matrix_set(energy_derivative, nspins)
     291              :          !
     292              :          CALL read_trexio(qs_env, trexio_filename=trexio_fn, &
     293              :                           mo_set_trexio=mos_trexio, &
     294            0 :                           energy_derivative=energy_derivative)
     295              :          !
     296            0 :          focc = 2.0_dp
     297            0 :          IF (nspins == 1) focc = 4.0_dp
     298            0 :          DO ispin = 1, nspins
     299            0 :             CALL get_mo_set(mo_set=mos_trexio(ispin), mo_coeff=mo_coeff, homo=nmos)
     300              :             CALL cp_dbcsr_sm_fm_multiply(energy_derivative(ispin)%matrix, mo_coeff, &
     301            0 :                                          cpmos(ispin), ncol=nmos, alpha=focc, beta=0.0_dp)
     302              :          END DO
     303              :          !
     304            0 :          CALL dbcsr_deallocate_matrix_set(energy_derivative)
     305              :       ELSE
     306              :          CALL read_trexio(qs_env, trexio_filename=trexio_fn, &
     307            0 :                           mo_set_trexio=mos_trexio)
     308              :       END IF
     309              :       !
     310            0 :       DO ispin = 1, nspins
     311            0 :          CALL get_mo_set(mo_set=mos_trexio(ispin), mo_coeff=mo_coeff, homo=nmos)
     312            0 :          CALL cp_fm_to_fm(mo_coeff, mo_ref(ispin), nmos)
     313            0 :          CALL deallocate_mo_set(mos_trexio(ispin))
     314              :       END DO
     315            0 :       DEALLOCATE (mos_trexio)
     316              : 
     317            0 :       CALL timestop(handle)
     318              : 
     319            0 :    END SUBROUTINE ec_ext_interface
     320              : 
     321              : ! **************************************************************************************************
     322              : 
     323              : ! **************************************************************************************************
     324              : !> \brief ...
     325              : !> \param qs_env ...
     326              : !> \param ec_env ...
     327              : !> \param calculate_forces ...
     328              : !> \param unit_nr ...
     329              : ! **************************************************************************************************
     330           48 :    SUBROUTINE ec_ext_debug(qs_env, ec_env, calculate_forces, unit_nr)
     331              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     332              :       TYPE(energy_correction_type), POINTER              :: ec_env
     333              :       LOGICAL, INTENT(IN)                                :: calculate_forces
     334              :       INTEGER, INTENT(IN)                                :: unit_nr
     335              : 
     336              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'ec_ext_debug'
     337              : 
     338              :       CHARACTER(LEN=default_string_length)               :: headline
     339              :       INTEGER                                            :: handle, ispin, nocc, nspins
     340              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     341           48 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_h, matrix_p, matrix_s
     342              :       TYPE(dft_control_type), POINTER                    :: dft_control
     343           48 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     344              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     345           48 :          POINTER                                         :: sab_orb
     346              :       TYPE(qs_rho_type), POINTER                         :: rho
     347              : 
     348           48 :       CALL timeset(routineN, handle)
     349              : 
     350              :       CALL get_qs_env(qs_env=qs_env, &
     351              :                       dft_control=dft_control, &
     352              :                       sab_orb=sab_orb, &
     353              :                       rho=rho, &
     354              :                       matrix_s_kp=matrix_s, &
     355           48 :                       matrix_h_kp=matrix_h)
     356              : 
     357           48 :       nspins = dft_control%nspins
     358           48 :       CALL get_qs_env(qs_env, mos=mos)
     359           96 :       DO ispin = 1, nspins
     360           48 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, homo=nocc)
     361           96 :          CALL cp_fm_to_fm(mo_coeff, ec_env%mo_occ(ispin), nocc)
     362              :       END DO
     363              : 
     364              :       ! Core Hamiltonian matrix
     365           48 :       IF (ASSOCIATED(ec_env%matrix_h)) CALL dbcsr_deallocate_matrix_set(ec_env%matrix_h)
     366           48 :       CALL dbcsr_allocate_matrix_set(ec_env%matrix_h, 1, 1)
     367           48 :       headline = "CORE HAMILTONIAN MATRIX"
     368           48 :       ALLOCATE (ec_env%matrix_h(1, 1)%matrix)
     369              :       CALL dbcsr_create(ec_env%matrix_h(1, 1)%matrix, name=TRIM(headline), &
     370           48 :                         template=matrix_h(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
     371           48 :       CALL cp_dbcsr_alloc_block_from_nbl(ec_env%matrix_h(1, 1)%matrix, sab_orb)
     372           48 :       CALL dbcsr_copy(ec_env%matrix_h(1, 1)%matrix, matrix_h(1, 1)%matrix)
     373              : 
     374              :       ! Get density matrix of reference calculation
     375           48 :       CALL qs_rho_get(rho, rho_ao_kp=matrix_p)
     376              :       ! Use Core energy as model energy
     377           48 :       CALL calculate_ptrace(ec_env%matrix_h, matrix_p, ec_env%ex, nspins)
     378              : 
     379           48 :       IF (calculate_forces) THEN
     380              :          ! force of model energy
     381           14 :          CALL ec_debug_force(qs_env, matrix_p, unit_nr)
     382              :       END IF
     383              : 
     384           48 :       CALL timestop(handle)
     385              : 
     386           48 :    END SUBROUTINE ec_ext_debug
     387              : 
     388              : ! **************************************************************************************************
     389              : !> \brief ...
     390              : !> \param qs_env ...
     391              : !> \param matrix_p ...
     392              : !> \param unit_nr ...
     393              : ! **************************************************************************************************
     394           14 :    SUBROUTINE ec_debug_force(qs_env, matrix_p, unit_nr)
     395              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     396              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_p
     397              :       INTEGER, INTENT(IN)                                :: unit_nr
     398              : 
     399              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'ec_debug_force'
     400              : 
     401              :       INTEGER                                            :: handle, iounit, nder, nimages
     402              :       LOGICAL                                            :: calculate_forces, debug_forces, &
     403              :                                                             debug_stress, use_virial
     404              :       REAL(KIND=dp)                                      :: fconv
     405              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: stdeb, sttot
     406              :       TYPE(cell_type), POINTER                           :: cell
     407           14 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: scrm
     408              :       TYPE(dft_control_type), POINTER                    :: dft_control
     409              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     410              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     411           14 :          POINTER                                         :: sab_orb
     412              :       TYPE(virial_type), POINTER                         :: virial
     413              : 
     414           14 :       CALL timeset(routineN, handle)
     415              : 
     416           14 :       debug_forces = .TRUE.
     417           14 :       debug_stress = .TRUE.
     418           14 :       iounit = unit_nr
     419              : 
     420           14 :       calculate_forces = .TRUE.
     421              : 
     422              :       ! no k-points possible
     423              :       CALL get_qs_env(qs_env=qs_env, &
     424              :                       cell=cell, &
     425              :                       dft_control=dft_control, &
     426              :                       para_env=para_env, &
     427           14 :                       virial=virial)
     428           14 :       nimages = dft_control%nimages
     429           14 :       IF (nimages /= 1) THEN
     430            0 :          CPABORT("K-points not implemented")
     431              :       END IF
     432              : 
     433              :       ! check for virial
     434           14 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
     435              : 
     436           14 :       fconv = 1.0E-9_dp*pascal/cell%deth
     437           14 :       IF (debug_stress .AND. use_virial) THEN
     438            0 :          sttot = virial%pv_virial
     439              :       END IF
     440              : 
     441              :       ! initialize src matrix
     442           14 :       NULLIFY (scrm)
     443           14 :       CALL dbcsr_allocate_matrix_set(scrm, 1, 1)
     444           14 :       ALLOCATE (scrm(1, 1)%matrix)
     445           14 :       CALL dbcsr_create(scrm(1, 1)%matrix, template=matrix_p(1, 1)%matrix)
     446           14 :       CALL get_qs_env(qs_env=qs_env, sab_orb=sab_orb)
     447           14 :       CALL cp_dbcsr_alloc_block_from_nbl(scrm(1, 1)%matrix, sab_orb)
     448              : 
     449              :       ! kinetic energy
     450              :       CALL kinetic_energy_matrix(qs_env, matrixkp_t=scrm, matrix_p=matrix_p, &
     451              :                                  calculate_forces=calculate_forces, &
     452           14 :                                  debug_forces=debug_forces, debug_stress=debug_stress)
     453              : 
     454           14 :       nder = 1
     455              :       CALL core_matrices(qs_env, scrm, matrix_p, calculate_forces, nder, &
     456           14 :                          debug_forces=debug_forces, debug_stress=debug_stress)
     457              : 
     458           14 :       IF (debug_stress .AND. use_virial) THEN
     459            0 :          stdeb = fconv*(virial%pv_virial - sttot)
     460            0 :          CALL para_env%sum(stdeb)
     461            0 :          IF (iounit > 0) WRITE (UNIT=iounit, FMT="(T2,A,T41,2(1X,ES19.11))") &
     462            0 :             'STRESS| Stress Pout*dHcore   ', one_third_sum_diag(stdeb), det_3x3(stdeb)
     463            0 :          IF (iounit > 0) WRITE (UNIT=iounit, FMT="(T2,A,T41,2(1X,ES19.11))") ' '
     464              :       END IF
     465              : 
     466              :       ! delete scr matrix
     467           14 :       CALL dbcsr_deallocate_matrix_set(scrm)
     468              : 
     469           14 :       CALL timestop(handle)
     470              : 
     471           14 :    END SUBROUTINE ec_debug_force
     472              : 
     473              : ! **************************************************************************************************
     474              : 
     475              : ! **************************************************************************************************
     476              : !> \brief ...
     477              : !> \param qs_env ...
     478              : !> \param ec_env ...
     479              : !> \param calc_forces ...
     480              : !> \param unit_nr ...
     481              : ! **************************************************************************************************
     482           48 :    SUBROUTINE ec_ext_setup(qs_env, ec_env, calc_forces, unit_nr)
     483              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     484              :       TYPE(energy_correction_type), POINTER              :: ec_env
     485              :       LOGICAL, INTENT(IN)                                :: calc_forces
     486              :       INTEGER, INTENT(IN)                                :: unit_nr
     487              : 
     488              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'ec_ext_setup'
     489              : 
     490              :       CHARACTER(LEN=default_string_length)               :: headline
     491              :       INTEGER                                            :: handle, ispin, nao, nocc, nspins
     492              :       REAL(KIND=dp)                                      :: a_max, c_max
     493              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct, mat_struct
     494              :       TYPE(cp_fm_type)                                   :: emat, ksmo, smo
     495           48 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_h, matrix_ks, matrix_p, matrix_s
     496              :       TYPE(dft_control_type), POINTER                    :: dft_control
     497              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     498           48 :          POINTER                                         :: sab_orb
     499              :       TYPE(qs_rho_type), POINTER                         :: rho
     500              : 
     501           48 :       CALL timeset(routineN, handle)
     502              : 
     503              :       CALL get_qs_env(qs_env=qs_env, &
     504              :                       dft_control=dft_control, &
     505              :                       sab_orb=sab_orb, &
     506              :                       rho=rho, &
     507              :                       matrix_s_kp=matrix_s, &
     508              :                       matrix_ks_kp=matrix_ks, &
     509           48 :                       matrix_h_kp=matrix_h)
     510              : 
     511           48 :       nspins = dft_control%nspins
     512              : 
     513              :       ! KS Hamiltonian matrix
     514           48 :       IF (ASSOCIATED(ec_env%matrix_ks)) CALL dbcsr_deallocate_matrix_set(ec_env%matrix_ks)
     515           48 :       CALL dbcsr_allocate_matrix_set(ec_env%matrix_ks, nspins, 1)
     516           48 :       headline = "HAMILTONIAN MATRIX"
     517           96 :       DO ispin = 1, nspins
     518           48 :          ALLOCATE (ec_env%matrix_ks(ispin, 1)%matrix)
     519              :          CALL dbcsr_create(ec_env%matrix_ks(ispin, 1)%matrix, name=TRIM(headline), &
     520           48 :                            template=matrix_ks(ispin, 1)%matrix, matrix_type=dbcsr_type_symmetric)
     521           48 :          CALL cp_dbcsr_alloc_block_from_nbl(ec_env%matrix_ks(ispin, 1)%matrix, sab_orb)
     522           96 :          CALL dbcsr_copy(ec_env%matrix_ks(ispin, 1)%matrix, matrix_ks(ispin, 1)%matrix)
     523              :       END DO
     524              : 
     525              :       ! Overlap matrix
     526           48 :       IF (ASSOCIATED(ec_env%matrix_s)) CALL dbcsr_deallocate_matrix_set(ec_env%matrix_s)
     527           48 :       CALL dbcsr_allocate_matrix_set(ec_env%matrix_s, 1, 1)
     528           48 :       headline = "OVERLAP MATRIX"
     529           48 :       ALLOCATE (ec_env%matrix_s(1, 1)%matrix)
     530              :       CALL dbcsr_create(ec_env%matrix_s(1, 1)%matrix, name=TRIM(headline), &
     531           48 :                         template=matrix_s(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
     532           48 :       CALL cp_dbcsr_alloc_block_from_nbl(ec_env%matrix_s(1, 1)%matrix, sab_orb)
     533           48 :       CALL dbcsr_copy(ec_env%matrix_s(1, 1)%matrix, matrix_s(1, 1)%matrix)
     534              : 
     535              :       ! density matrix
     536              :       ! Get density matrix of reference calculation
     537           48 :       CALL qs_rho_get(rho, rho_ao_kp=matrix_p)
     538           48 :       IF (ASSOCIATED(ec_env%matrix_p)) CALL dbcsr_deallocate_matrix_set(ec_env%matrix_p)
     539           48 :       CALL dbcsr_allocate_matrix_set(ec_env%matrix_p, nspins, 1)
     540           48 :       headline = "DENSITY MATRIX"
     541           96 :       DO ispin = 1, nspins
     542           48 :          ALLOCATE (ec_env%matrix_p(ispin, 1)%matrix)
     543              :          CALL dbcsr_create(ec_env%matrix_p(ispin, 1)%matrix, name=TRIM(headline), &
     544           48 :                            template=matrix_p(ispin, 1)%matrix, matrix_type=dbcsr_type_symmetric)
     545           48 :          CALL cp_dbcsr_alloc_block_from_nbl(ec_env%matrix_p(ispin, 1)%matrix, sab_orb)
     546           96 :          CALL dbcsr_copy(ec_env%matrix_p(ispin, 1)%matrix, matrix_p(ispin, 1)%matrix)
     547              :       END DO
     548              : 
     549           48 :       IF (calc_forces) THEN
     550              :          ! energy weighted density matrix
     551              :          ! for security, we recalculate W here (stored in qs_env)
     552           14 :          IF (ASSOCIATED(ec_env%matrix_w)) CALL dbcsr_deallocate_matrix_set(ec_env%matrix_w)
     553           14 :          CALL dbcsr_allocate_matrix_set(ec_env%matrix_w, nspins, 1)
     554           14 :          headline = "ENERGY WEIGHTED DENSITY MATRIX"
     555           28 :          DO ispin = 1, nspins
     556           14 :             ALLOCATE (ec_env%matrix_w(ispin, 1)%matrix)
     557              :             CALL dbcsr_create(ec_env%matrix_w(ispin, 1)%matrix, name=TRIM(headline), &
     558           14 :                               template=matrix_p(ispin, 1)%matrix, matrix_type=dbcsr_type_symmetric)
     559           14 :             CALL cp_dbcsr_alloc_block_from_nbl(ec_env%matrix_w(ispin, 1)%matrix, sab_orb)
     560           28 :             CALL dbcsr_set(ec_env%matrix_w(ispin, 1)%matrix, 0.0_dp)
     561              :          END DO
     562              : 
     563              :          ! hz matrix
     564           14 :          IF (ASSOCIATED(ec_env%matrix_hz)) CALL dbcsr_deallocate_matrix_set(ec_env%matrix_hz)
     565           14 :          CALL dbcsr_allocate_matrix_set(ec_env%matrix_hz, nspins)
     566           14 :          headline = "Hz MATRIX"
     567           28 :          DO ispin = 1, nspins
     568           14 :             ALLOCATE (ec_env%matrix_hz(ispin)%matrix)
     569              :             CALL dbcsr_create(ec_env%matrix_hz(ispin)%matrix, name=TRIM(headline), &
     570           14 :                               template=matrix_s(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
     571           14 :             CALL cp_dbcsr_alloc_block_from_nbl(ec_env%matrix_hz(ispin)%matrix, sab_orb)
     572           28 :             CALL dbcsr_set(ec_env%matrix_hz(ispin)%matrix, 0.0_dp)
     573              :          END DO
     574              : 
     575              :          ! Test for consistency of orbitals and KS matrix
     576           28 :          DO ispin = 1, nspins
     577           14 :             mat_struct => ec_env%mo_occ(ispin)%matrix_struct
     578           14 :             CALL cp_fm_create(ksmo, mat_struct)
     579           14 :             CALL cp_fm_get_info(ksmo, nrow_global=nao, ncol_global=nocc)
     580              :             CALL cp_dbcsr_sm_fm_multiply(ec_env%matrix_ks(ispin, 1)%matrix, ec_env%mo_occ(ispin), &
     581           14 :                                          ksmo, nocc, alpha=1.0_dp, beta=0.0_dp)
     582           14 :             CALL cp_fm_create(smo, mat_struct)
     583              :             CALL cp_dbcsr_sm_fm_multiply(ec_env%matrix_s(1, 1)%matrix, ec_env%mo_occ(ispin), &
     584           14 :                                          smo, nocc, alpha=1.0_dp, beta=0.0_dp)
     585              :             CALL cp_fm_struct_create(fm_struct, ncol_global=nocc, nrow_global=nocc, &
     586           14 :                                      template_fmstruct=mat_struct)
     587           14 :             CALL cp_fm_create(emat, fm_struct)
     588           14 :             CALL parallel_gemm('T', 'N', nocc, nocc, nao, 1.0_dp, ec_env%mo_occ(ispin), ksmo, 0.0_dp, emat)
     589           14 :             CALL parallel_gemm('N', 'N', nao, nocc, nocc, -1.0_dp, smo, emat, 1.0_dp, ksmo)
     590           14 :             CALL cp_fm_maxabsval(ksmo, a_max)
     591           14 :             CALL cp_fm_struct_release(fm_struct)
     592           14 :             CALL cp_fm_release(smo)
     593           14 :             CALL cp_fm_release(ksmo)
     594           14 :             CALL cp_fm_release(emat)
     595           14 :             CALL cp_fm_maxabsval(ec_env%mo_occ(ispin), c_max)
     596           84 :             IF (unit_nr > 0) THEN
     597            7 :                WRITE (unit_nr, "(T3,A,T50,I2,T61,F20.12)") "External:: Max value of MO coeficients", ispin, c_max
     598            7 :                WRITE (unit_nr, "(T3,A,T50,I2,T61,F20.12)") "External:: Max value of MO gradients", ispin, a_max
     599              :             END IF
     600              :          END DO
     601              :       END IF
     602              : 
     603           48 :       CALL timestop(handle)
     604              : 
     605           48 :    END SUBROUTINE ec_ext_setup
     606              : 
     607              : ! **************************************************************************************************
     608              : !> \brief ...
     609              : !> \param cpmos ...
     610              : !> \param mo_ref ...
     611              : !> \param mo_occ ...
     612              : !> \param matrix_s ...
     613              : !> \param orbrot_index ...
     614              : !> \param phase_index ...
     615              : !> \param unit_nr ...
     616              : ! **************************************************************************************************
     617           14 :    SUBROUTINE align_vectors(cpmos, mo_ref, mo_occ, matrix_s, orbrot_index, phase_index, unit_nr)
     618              :       TYPE(cp_fm_type), INTENT(IN)                       :: cpmos, mo_ref, mo_occ
     619              :       TYPE(dbcsr_type), POINTER                          :: matrix_s
     620              :       REAL(KIND=dp), INTENT(OUT)                         :: orbrot_index, phase_index
     621              :       INTEGER, INTENT(IN)                                :: unit_nr
     622              : 
     623              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'align_vectors'
     624              : 
     625              :       INTEGER                                            :: handle, i, nao, nocc, scg
     626              :       REAL(KIND=dp)                                      :: a_max
     627              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: diag
     628              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct, mat_struct
     629              :       TYPE(cp_fm_type)                                   :: emat, smo
     630              : 
     631           14 :       CALL timeset(routineN, handle)
     632              : 
     633           14 :       mat_struct => cpmos%matrix_struct
     634           14 :       CALL cp_fm_create(smo, mat_struct)
     635           14 :       CALL cp_fm_get_info(smo, nrow_global=nao, ncol_global=nocc)
     636           14 :       CALL cp_dbcsr_sm_fm_multiply(matrix_s, mo_occ, smo, nocc, alpha=1.0_dp, beta=0.0_dp)
     637              :       CALL cp_fm_struct_create(fm_struct, ncol_global=nocc, nrow_global=nocc, &
     638           14 :                                template_fmstruct=mat_struct)
     639           14 :       CALL cp_fm_create(emat, fm_struct)
     640           14 :       CALL parallel_gemm('T', 'N', nocc, nocc, nao, 1.0_dp, mo_ref, smo, 0.0_dp, emat)
     641           14 :       CALL parallel_gemm('N', 'N', nao, nocc, nocc, 1.0_dp, cpmos, emat, 0.0_dp, smo)
     642           14 :       CALL cp_fm_to_fm(smo, cpmos)
     643           14 :       CALL cp_fm_to_fm(mo_occ, mo_ref)
     644              :       !
     645           42 :       ALLOCATE (diag(nocc))
     646           14 :       CALL cp_fm_get_diag(emat, diag)
     647           68 :       a_max = nocc - SUM(diag)
     648           14 :       scg = 0
     649           68 :       DO i = 1, nocc
     650           68 :          IF (ABS(diag(i) + 1.0_dp) < 0.001) scg = scg + 1
     651              :       END DO
     652           14 :       IF (unit_nr > 0) THEN
     653            7 :          WRITE (unit_nr, "(T3,A,T61,F20.8)") "External:: Orbital rotation index", a_max
     654            7 :          WRITE (unit_nr, "(T3,A,T71,I10)") "External:: Number of orbital phase changes", scg
     655              :       END IF
     656           14 :       orbrot_index = a_max
     657           14 :       phase_index = REAL(scg, KIND=dp)
     658              : 
     659           14 :       DEALLOCATE (diag)
     660           14 :       CALL cp_fm_struct_release(fm_struct)
     661           14 :       CALL cp_fm_release(smo)
     662           14 :       CALL cp_fm_release(emat)
     663              : 
     664           14 :       CALL timestop(handle)
     665              : 
     666           28 :    END SUBROUTINE align_vectors
     667              : 
     668              : ! **************************************************************************************************
     669              : !> \brief ...
     670              : !> \param qs_env ...
     671              : !> \param cpmos ...
     672              : !> \param mo_occ ...
     673              : !> \param matrix_r ...
     674              : !> \param unit_nr ...
     675              : !> \param debug_forces ...
     676              : !> \param debug_stress ...
     677              : ! **************************************************************************************************
     678           24 :    SUBROUTINE matrix_r_forces(qs_env, cpmos, mo_occ, matrix_r, unit_nr, &
     679              :                               debug_forces, debug_stress)
     680              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     681              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: cpmos, mo_occ
     682              :       TYPE(dbcsr_type), POINTER                          :: matrix_r
     683              :       INTEGER, INTENT(IN)                                :: unit_nr
     684              :       LOGICAL, INTENT(IN), OPTIONAL                      :: debug_forces, debug_stress
     685              : 
     686              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'matrix_r_forces'
     687              : 
     688              :       INTEGER                                            :: handle, iounit, ispin, nao, nocc, nspins
     689              :       LOGICAL                                            :: my_debug_forces, my_debug_stress, &
     690              :                                                             use_virial
     691              :       REAL(KIND=dp)                                      :: fconv, focc
     692              :       REAL(KIND=dp), DIMENSION(3)                        :: fodeb
     693              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: stdeb
     694              :       TYPE(cell_type), POINTER                           :: cell
     695              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct, mat_struct
     696              :       TYPE(cp_fm_type)                                   :: chcmat, rcvec
     697           24 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: scrm
     698              :       TYPE(dft_control_type), POINTER                    :: dft_control
     699              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     700              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     701           24 :          POINTER                                         :: sab_orb
     702           24 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
     703              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     704              :       TYPE(virial_type), POINTER                         :: virial
     705              : 
     706           24 :       CALL timeset(routineN, handle)
     707              : 
     708           24 :       my_debug_forces = .TRUE.
     709           24 :       my_debug_stress = .TRUE.
     710           24 :       IF (PRESENT(debug_forces)) my_debug_forces = debug_forces
     711           24 :       IF (PRESENT(debug_stress)) my_debug_stress = debug_stress
     712           24 :       iounit = unit_nr
     713              : 
     714           24 :       nspins = SIZE(mo_occ)
     715           24 :       focc = 1.0_dp
     716           24 :       IF (nspins == 1) focc = 2.0_dp
     717           24 :       focc = 0.25_dp*focc
     718              : 
     719           24 :       CALL dbcsr_set(matrix_r, 0.0_dp)
     720           48 :       DO ispin = 1, nspins
     721           24 :          CALL cp_fm_get_info(cpmos(ispin), matrix_struct=fm_struct, nrow_global=nao, ncol_global=nocc)
     722           24 :          CALL cp_fm_create(rcvec, fm_struct)
     723           24 :          CALL cp_fm_struct_create(mat_struct, nrow_global=nocc, ncol_global=nocc, template_fmstruct=fm_struct)
     724           24 :          CALL cp_fm_create(chcmat, mat_struct)
     725           24 :          CALL parallel_gemm("T", "N", nocc, nocc, nao, 1.0_dp, mo_occ(ispin), cpmos(ispin), 0.0_dp, chcmat)
     726           24 :          CALL parallel_gemm("N", "N", nao, nocc, nocc, 1.0_dp, mo_occ(ispin), chcmat, 0.0_dp, rcvec)
     727           24 :          CALL cp_dbcsr_plus_fm_fm_t(matrix_r, matrix_v=rcvec, matrix_g=mo_occ(ispin), ncol=nocc, alpha=focc)
     728           24 :          CALL cp_fm_struct_release(mat_struct)
     729           24 :          CALL cp_fm_release(rcvec)
     730           96 :          CALL cp_fm_release(chcmat)
     731              :       END DO
     732              : 
     733              :       CALL get_qs_env(qs_env=qs_env, &
     734              :                       cell=cell, &
     735              :                       dft_control=dft_control, &
     736              :                       force=force, &
     737              :                       ks_env=ks_env, &
     738              :                       sab_orb=sab_orb, &
     739              :                       para_env=para_env, &
     740           24 :                       virial=virial)
     741              :       ! check for virial
     742           24 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
     743           24 :       fconv = 1.0E-9_dp*pascal/cell%deth
     744              : 
     745           60 :       IF (my_debug_forces) fodeb(1:3) = force(1)%overlap(1:3, 1)
     746           24 :       IF (my_debug_stress .AND. use_virial) stdeb = virial%pv_overlap
     747           24 :       NULLIFY (scrm)
     748              :       CALL build_overlap_matrix(ks_env, matrix_s=scrm, &
     749              :                                 matrix_name="OVERLAP MATRIX", &
     750              :                                 basis_type_a="ORB", basis_type_b="ORB", &
     751              :                                 sab_nl=sab_orb, calculate_forces=.TRUE., &
     752           24 :                                 matrix_p=matrix_r)
     753           24 :       IF (my_debug_forces) THEN
     754           48 :          fodeb(1:3) = force(1)%overlap(1:3, 1) - fodeb(1:3)
     755           12 :          CALL para_env%sum(fodeb)
     756           12 :          IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Wz*dS ", fodeb
     757              :       END IF
     758           24 :       IF (my_debug_stress .AND. use_virial) THEN
     759            0 :          stdeb = fconv*(virial%pv_overlap - stdeb)
     760            0 :          CALL para_env%sum(stdeb)
     761            0 :          IF (iounit > 0) WRITE (UNIT=iounit, FMT="(T2,A,T41,2(1X,ES19.11))") &
     762            0 :             'STRESS| Wz   ', one_third_sum_diag(stdeb), det_3x3(stdeb)
     763              :       END IF
     764           24 :       CALL dbcsr_deallocate_matrix_set(scrm)
     765              : 
     766           24 :       CALL timestop(handle)
     767              : 
     768           24 :    END SUBROUTINE matrix_r_forces
     769              : 
     770              : END MODULE ec_external
        

Generated by: LCOV version 2.0-1