LCOV - code coverage report
Current view: top level - src - qs_efield_berry.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b4bd748) Lines: 617 651 94.8 %
Date: 2025-03-09 07:56:22 Functions: 5 5 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Calculates the energy contribution and the mo_derivative of
      10             : !>        a static periodic electric field
      11             : !> \par History
      12             : !>      none
      13             : !> \author fschiff (06.2010)
      14             : ! **************************************************************************************************
      15             : MODULE qs_efield_berry
      16             :    USE ai_moments,                      ONLY: cossin
      17             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      18             :                                               get_atomic_kind,&
      19             :                                               get_atomic_kind_set
      20             :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      21             :                                               gto_basis_set_type
      22             :    USE block_p_types,                   ONLY: block_p_type
      23             :    USE cell_types,                      ONLY: cell_type,&
      24             :                                               pbc
      25             :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_scale_and_add_fm,&
      26             :                                               cp_cfm_solve
      27             :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      28             :                                               cp_cfm_release,&
      29             :                                               cp_cfm_set_all,&
      30             :                                               cp_cfm_type
      31             :    USE cp_control_types,                ONLY: dft_control_type
      32             :    USE cp_dbcsr_api,                    ONLY: dbcsr_copy,&
      33             :                                               dbcsr_get_block_p,&
      34             :                                               dbcsr_p_type,&
      35             :                                               dbcsr_set,&
      36             :                                               dbcsr_type
      37             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      38             :                                               copy_fm_to_dbcsr,&
      39             :                                               cp_dbcsr_plus_fm_fm_t,&
      40             :                                               cp_dbcsr_sm_fm_multiply,&
      41             :                                               dbcsr_deallocate_matrix_set
      42             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale_and_add
      43             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      44             :                                               cp_fm_struct_release,&
      45             :                                               cp_fm_struct_type
      46             :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      47             :                                               cp_fm_release,&
      48             :                                               cp_fm_set_all,&
      49             :                                               cp_fm_type
      50             :    USE kinds,                           ONLY: dp
      51             :    USE mathconstants,                   ONLY: gaussi,&
      52             :                                               pi,&
      53             :                                               twopi,&
      54             :                                               z_one,&
      55             :                                               z_zero
      56             :    USE message_passing,                 ONLY: mp_para_env_type
      57             :    USE orbital_pointers,                ONLY: ncoset
      58             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      59             :    USE particle_types,                  ONLY: particle_type
      60             :    USE qs_energy_types,                 ONLY: qs_energy_type
      61             :    USE qs_environment_types,            ONLY: get_qs_env,&
      62             :                                               qs_environment_type,&
      63             :                                               set_qs_env
      64             :    USE qs_force_types,                  ONLY: qs_force_type
      65             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      66             :                                               get_qs_kind_set,&
      67             :                                               qs_kind_type
      68             :    USE qs_mo_types,                     ONLY: get_mo_set,&
      69             :                                               mo_set_type
      70             :    USE qs_moments,                      ONLY: build_berry_moment_matrix
      71             :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      72             :                                               neighbor_list_iterate,&
      73             :                                               neighbor_list_iterator_create,&
      74             :                                               neighbor_list_iterator_p_type,&
      75             :                                               neighbor_list_iterator_release,&
      76             :                                               neighbor_list_set_p_type
      77             :    USE qs_period_efield_types,          ONLY: efield_berry_type,&
      78             :                                               init_efield_matrices,&
      79             :                                               set_efield_matrices
      80             :    USE virial_methods,                  ONLY: virial_pair_force
      81             :    USE virial_types,                    ONLY: virial_type
      82             : #include "./base/base_uses.f90"
      83             : 
      84             :    IMPLICIT NONE
      85             : 
      86             :    PRIVATE
      87             : 
      88             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_efield_berry'
      89             : 
      90             :    ! *** Public subroutines ***
      91             : 
      92             :    PUBLIC :: qs_efield_berry_phase
      93             : 
      94             : ! **************************************************************************************************
      95             : 
      96             : CONTAINS
      97             : 
      98             : ! **************************************************************************************************
      99             : 
     100             : ! **************************************************************************************************
     101             : !> \brief ...
     102             : !> \param qs_env ...
     103             : !> \param just_energy ...
     104             : !> \param calculate_forces ...
     105             : ! **************************************************************************************************
     106       98303 :    SUBROUTINE qs_efield_berry_phase(qs_env, just_energy, calculate_forces)
     107             : 
     108             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     109             :       LOGICAL, INTENT(IN)                                :: just_energy, calculate_forces
     110             : 
     111             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_efield_berry_phase'
     112             : 
     113             :       INTEGER                                            :: handle
     114             :       LOGICAL                                            :: s_mstruct_changed
     115             :       TYPE(dft_control_type), POINTER                    :: dft_control
     116             : 
     117       98303 :       CALL timeset(routineN, handle)
     118             : 
     119       98303 :       NULLIFY (dft_control)
     120             :       CALL get_qs_env(qs_env, s_mstruct_changed=s_mstruct_changed, &
     121       98303 :                       dft_control=dft_control)
     122             : 
     123       98303 :       IF (dft_control%apply_period_efield) THEN
     124             :          ! check if the periodic efield should be applied in the current step
     125        2520 :          IF (dft_control%period_efield%start_frame <= qs_env%sim_step .AND. &
     126             :              (dft_control%period_efield%end_frame == -1 .OR. dft_control%period_efield%end_frame >= qs_env%sim_step)) THEN
     127             : 
     128        2394 :             IF (s_mstruct_changed) CALL qs_efield_integrals(qs_env)
     129        2394 :             IF (dft_control%period_efield%displacement_field) THEN
     130         898 :                CALL qs_dispfield_derivatives(qs_env, just_energy, calculate_forces)
     131             :             ELSE
     132        1496 :                CALL qs_efield_derivatives(qs_env, just_energy, calculate_forces)
     133             :             END IF
     134             :          END IF
     135             :       END IF
     136             : 
     137       98303 :       CALL timestop(handle)
     138             : 
     139       98303 :    END SUBROUTINE qs_efield_berry_phase
     140             : 
     141             : ! **************************************************************************************************
     142             : !> \brief ...
     143             : !> \param qs_env ...
     144             : ! **************************************************************************************************
     145         192 :    SUBROUTINE qs_efield_integrals(qs_env)
     146             : 
     147             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     148             : 
     149             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_efield_integrals'
     150             : 
     151             :       INTEGER                                            :: handle, i
     152             :       REAL(dp), DIMENSION(3)                             :: kvec
     153             :       TYPE(cell_type), POINTER                           :: cell
     154         192 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: cosmat, matrix_s, sinmat
     155             :       TYPE(dft_control_type), POINTER                    :: dft_control
     156             :       TYPE(efield_berry_type), POINTER                   :: efield
     157             : 
     158         192 :       CALL timeset(routineN, handle)
     159         192 :       CPASSERT(ASSOCIATED(qs_env))
     160             : 
     161         192 :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control)
     162         192 :       NULLIFY (matrix_s)
     163         192 :       CALL get_qs_env(qs_env=qs_env, efield=efield, cell=cell, matrix_s=matrix_s)
     164         192 :       CALL init_efield_matrices(efield)
     165        1344 :       ALLOCATE (cosmat(3), sinmat(3))
     166         768 :       DO i = 1, 3
     167         576 :          ALLOCATE (cosmat(i)%matrix, sinmat(i)%matrix)
     168             : 
     169         576 :          CALL dbcsr_copy(cosmat(i)%matrix, matrix_s(1)%matrix, 'COS MAT')
     170         576 :          CALL dbcsr_copy(sinmat(i)%matrix, matrix_s(1)%matrix, 'SIN MAT')
     171         576 :          CALL dbcsr_set(cosmat(i)%matrix, 0.0_dp)
     172         576 :          CALL dbcsr_set(sinmat(i)%matrix, 0.0_dp)
     173             : 
     174        2304 :          kvec(:) = twopi*cell%h_inv(i, :)
     175         768 :          CALL build_berry_moment_matrix(qs_env, cosmat(i)%matrix, sinmat(i)%matrix, kvec)
     176             :       END DO
     177         192 :       CALL set_efield_matrices(efield=efield, cosmat=cosmat, sinmat=sinmat)
     178         192 :       CALL set_qs_env(qs_env=qs_env, efield=efield)
     179         192 :       CALL timestop(handle)
     180             : 
     181         192 :    END SUBROUTINE qs_efield_integrals
     182             : 
     183             : ! **************************************************************************************************
     184             : !> \brief ...
     185             : !> \param qs_env ...
     186             : !> \param just_energy ...
     187             : !> \param calculate_forces ...
     188             : ! **************************************************************************************************
     189        1496 :    SUBROUTINE qs_efield_derivatives(qs_env, just_energy, calculate_forces)
     190             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     191             :       LOGICAL, INTENT(IN)                                :: just_energy, calculate_forces
     192             : 
     193             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_efield_derivatives'
     194             : 
     195             :       COMPLEX(dp)                                        :: zdet, zdeta, zi(3)
     196             :       INTEGER :: atom_a, atom_b, handle, i, ia, iatom, icol, idir, ikind, irow, iset, ispin, j, &
     197             :          jatom, jkind, jset, ldab, ldsa, ldsb, lsab, n1, n2, nao, natom, ncoa, ncob, nkind, nmo, &
     198             :          nseta, nsetb, sgfa, sgfb
     199        1496 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind
     200        1496 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
     201        1496 :                                                             npgfb, nsgfa, nsgfb
     202        1496 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
     203             :       LOGICAL                                            :: found, uniform, use_virial
     204             :       REAL(dp)                                           :: charge, ci(3), cqi(3), dab, dd, &
     205             :                                                             ener_field, f0, fab, fieldpol(3), &
     206             :                                                             focc, fpolvec(3), hmat(3, 3), occ, &
     207             :                                                             qi(3), strength, ti(3)
     208             :       REAL(dp), DIMENSION(3)                             :: forcea, forceb, kvec, ra, rab, rb, ria
     209        2992 :       REAL(dp), DIMENSION(:, :), POINTER                 :: cosab, iblock, rblock, sinab, work
     210        2992 :       REAL(dp), DIMENSION(:, :, :), POINTER              :: dcosab, dsinab
     211        1496 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
     212        1496 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb
     213        1496 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     214       26928 :       TYPE(block_p_type), DIMENSION(3, 2)                :: dcost, dsint
     215             :       TYPE(cell_type), POINTER                           :: cell
     216        1496 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: eigrmat, inv_mat
     217             :       TYPE(cp_fm_struct_type), POINTER                   :: tmp_fm_struct
     218        1496 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: mo_coeff_tmp, mo_derivs_tmp
     219        1496 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: inv_work, op_fm_set, opvec
     220             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     221        1496 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, mo_derivs
     222        1496 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: tempmat
     223             :       TYPE(dbcsr_type), POINTER                          :: cosmat, mo_coeff_b, sinmat
     224             :       TYPE(dft_control_type), POINTER                    :: dft_control
     225             :       TYPE(efield_berry_type), POINTER                   :: efield
     226        1496 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     227             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     228        1496 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     229             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     230             :       TYPE(neighbor_list_iterator_p_type), &
     231        1496 :          DIMENSION(:), POINTER                           :: nl_iterator
     232             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     233        1496 :          POINTER                                         :: sab_orb
     234        1496 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     235             :       TYPE(qs_energy_type), POINTER                      :: energy
     236        1496 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
     237        1496 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     238             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     239             :       TYPE(virial_type), POINTER                         :: virial
     240             : 
     241        1496 :       CALL timeset(routineN, handle)
     242             : 
     243        1496 :       NULLIFY (dft_control, cell, particle_set)
     244             :       CALL get_qs_env(qs_env, dft_control=dft_control, cell=cell, &
     245        1496 :                       particle_set=particle_set, virial=virial)
     246        1496 :       NULLIFY (qs_kind_set, efield, para_env, sab_orb)
     247             :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
     248        1496 :                       efield=efield, energy=energy, para_env=para_env, sab_orb=sab_orb)
     249             : 
     250             :       ! calculate stress only if forces requested also
     251        1496 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
     252           0 :       use_virial = use_virial .AND. calculate_forces
     253             :       ! disable stress calculation
     254             :       IF (use_virial) THEN
     255           0 :          CPABORT("Stress tensor for periodic E-field not implemented")
     256             :       END IF
     257             : 
     258             :       ! if an intensities list is given, select the value for the current step
     259        1496 :       strength = dft_control%period_efield%strength
     260        1496 :       IF (ALLOCATED(dft_control%period_efield%strength_list)) THEN
     261             :          strength = dft_control%period_efield%strength_list(MOD(qs_env%sim_step &
     262         336 :                                         - dft_control%period_efield%start_frame, SIZE(dft_control%period_efield%strength_list)) + 1)
     263             :       END IF
     264             : 
     265        5984 :       fieldpol = dft_control%period_efield%polarisation
     266       10472 :       fieldpol = fieldpol/SQRT(DOT_PRODUCT(fieldpol, fieldpol))
     267        5984 :       fieldpol = -fieldpol*strength
     268       19448 :       hmat = cell%hmat(:, :)/twopi
     269        5984 :       DO idir = 1, 3
     270        5984 :          fpolvec(idir) = fieldpol(1)*hmat(1, idir) + fieldpol(2)*hmat(2, idir) + fieldpol(3)*hmat(3, idir)
     271             :       END DO
     272             : 
     273             :       ! nuclear contribution
     274        1496 :       natom = SIZE(particle_set)
     275        1496 :       IF (calculate_forces) THEN
     276          76 :          CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, force=force)
     277          76 :          CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind)
     278             :       END IF
     279        5984 :       zi(:) = CMPLX(1._dp, 0._dp, dp)
     280        5304 :       DO ia = 1, natom
     281        3808 :          CALL get_atomic_kind(particle_set(ia)%atomic_kind, kind_number=ikind)
     282        3808 :          CALL get_qs_kind(qs_kind_set(ikind), core_charge=charge)
     283       15232 :          ria = particle_set(ia)%r
     284       15232 :          ria = pbc(ria, cell)
     285       15232 :          DO idir = 1, 3
     286       45696 :             kvec(:) = twopi*cell%h_inv(idir, :)
     287       45696 :             dd = SUM(kvec(:)*ria(:))
     288       11424 :             zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)**charge
     289       15232 :             zi(idir) = zi(idir)*zdeta
     290             :          END DO
     291        3808 :          IF (calculate_forces) THEN
     292         218 :             IF (para_env%mepos == 0) THEN
     293         109 :                iatom = atom_of_kind(ia)
     294         436 :                forcea(:) = fieldpol(:)*charge
     295         436 :                force(ikind)%efield(:, iatom) = force(ikind)%efield(:, iatom) + forcea(:)
     296             :             END IF
     297             :          END IF
     298        9112 :          IF (use_virial) THEN
     299           0 :             IF (para_env%mepos == 0) &
     300           0 :                CALL virial_pair_force(virial%pv_virial, 1.0_dp, forcea, ria)
     301             :          END IF
     302             :       END DO
     303        5984 :       qi = AIMAG(LOG(zi))
     304             : 
     305             :       ! check uniform occupation
     306        1496 :       NULLIFY (mos)
     307        1496 :       CALL get_qs_env(qs_env=qs_env, mos=mos)
     308        3052 :       DO ispin = 1, dft_control%nspins
     309        1556 :          CALL get_mo_set(mo_set=mos(ispin), maxocc=occ, uniform_occupation=uniform)
     310        3052 :          IF (.NOT. uniform) THEN
     311           0 :             CPABORT("Berry phase moments for non uniform MOs' occupation numbers not implemented")
     312             :          END IF
     313             :       END DO
     314             : 
     315        1496 :       NULLIFY (mo_derivs)
     316        1496 :       CALL get_qs_env(qs_env=qs_env, mo_derivs=mo_derivs)
     317             :       ! initialize all work matrices needed
     318        9156 :       ALLOCATE (op_fm_set(2, dft_control%nspins))
     319        9156 :       ALLOCATE (opvec(2, dft_control%nspins))
     320        6044 :       ALLOCATE (eigrmat(dft_control%nspins))
     321        6044 :       ALLOCATE (inv_mat(dft_control%nspins))
     322        9156 :       ALLOCATE (inv_work(2, dft_control%nspins))
     323        6044 :       ALLOCATE (mo_derivs_tmp(SIZE(mo_derivs)))
     324        4548 :       ALLOCATE (mo_coeff_tmp(SIZE(mo_derivs)))
     325             : 
     326             :       ! Allocate temp matrices for the wavefunction derivatives
     327        3052 :       DO ispin = 1, dft_control%nspins
     328        1556 :          NULLIFY (tmp_fm_struct, mo_coeff)
     329        1556 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nao=nao, nmo=nmo)
     330             :          CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=nmo, &
     331        1556 :                                   ncol_global=nmo, para_env=para_env, context=mo_coeff%matrix_struct%context)
     332        1556 :          CALL cp_fm_create(mo_derivs_tmp(ispin), mo_coeff%matrix_struct)
     333        1556 :          CALL cp_fm_create(mo_coeff_tmp(ispin), mo_coeff%matrix_struct)
     334        1556 :          CALL copy_dbcsr_to_fm(mo_derivs(ispin)%matrix, mo_derivs_tmp(ispin))
     335        4668 :          DO i = 1, SIZE(op_fm_set, 1)
     336        3112 :             CALL cp_fm_create(opvec(i, ispin), mo_coeff%matrix_struct)
     337        3112 :             CALL cp_fm_create(op_fm_set(i, ispin), tmp_fm_struct)
     338        4668 :             CALL cp_fm_create(inv_work(i, ispin), op_fm_set(i, ispin)%matrix_struct)
     339             :          END DO
     340        1556 :          CALL cp_cfm_create(eigrmat(ispin), op_fm_set(1, ispin)%matrix_struct)
     341        1556 :          CALL cp_cfm_create(inv_mat(ispin), op_fm_set(1, ispin)%matrix_struct)
     342        4608 :          CALL cp_fm_struct_release(tmp_fm_struct)
     343             :       END DO
     344             :       ! temp matrices for force calculation
     345        1496 :       IF (calculate_forces) THEN
     346          76 :          NULLIFY (matrix_s)
     347          76 :          CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s)
     348         480 :          ALLOCATE (tempmat(2, dft_control%nspins))
     349         160 :          DO ispin = 1, dft_control%nspins
     350          84 :             ALLOCATE (tempmat(1, ispin)%matrix, tempmat(2, ispin)%matrix)
     351          84 :             CALL dbcsr_copy(tempmat(1, ispin)%matrix, matrix_s(1)%matrix, 'TEMPMAT')
     352          84 :             CALL dbcsr_copy(tempmat(2, ispin)%matrix, matrix_s(1)%matrix, 'TEMPMAT')
     353          84 :             CALL dbcsr_set(tempmat(1, ispin)%matrix, 0.0_dp)
     354         160 :             CALL dbcsr_set(tempmat(2, ispin)%matrix, 0.0_dp)
     355             :          END DO
     356             :          ! integration
     357          76 :          CALL get_qs_kind_set(qs_kind_set, maxco=ldab, maxsgf=lsab)
     358         608 :          ALLOCATE (cosab(ldab, ldab), sinab(ldab, ldab), work(ldab, ldab))
     359         532 :          ALLOCATE (dcosab(ldab, ldab, 3), dsinab(ldab, ldab, 3))
     360          76 :          lsab = MAX(ldab, lsab)
     361         380 :          DO i = 1, 3
     362        1368 :             ALLOCATE (dcost(i, 1)%block(lsab, lsab), dsint(i, 1)%block(lsab, lsab))
     363        1216 :             ALLOCATE (dcost(i, 2)%block(lsab, lsab), dsint(i, 2)%block(lsab, lsab))
     364             :          END DO
     365             :       END IF
     366             : 
     367             :       !Start the MO derivative calculation
     368             :       !loop over all cell vectors
     369        5984 :       DO idir = 1, 3
     370        4488 :          ci(idir) = 0.0_dp
     371             :          zi(idir) = z_zero
     372        5984 :          IF (ABS(fpolvec(idir)) .GT. 1.0E-12_dp) THEN
     373        2722 :             cosmat => efield%cosmat(idir)%matrix
     374        2722 :             sinmat => efield%sinmat(idir)%matrix
     375             :             !evaluate the expression needed for the derivative (S_berry * C  and [C^T S_berry C]^-1)
     376             :             !first step S_berry * C  and C^T S_berry C
     377        5504 :             DO ispin = 1, dft_control%nspins ! spin
     378        2782 :                IF (mos(ispin)%use_mo_coeff_b) THEN
     379        2782 :                   CALL get_mo_set(mo_set=mos(ispin), nao=nao, mo_coeff_b=mo_coeff_b, nmo=nmo)
     380        2782 :                   CALL copy_dbcsr_to_fm(mo_coeff_b, mo_coeff_tmp(ispin))
     381             :                ELSE
     382           0 :                   CALL get_mo_set(mo_set=mos(ispin), nao=nao, mo_coeff=mo_coeff, nmo=nmo)
     383           0 :                   mo_coeff_tmp(ispin) = mo_coeff
     384             :                END IF
     385        2782 :                CALL cp_dbcsr_sm_fm_multiply(cosmat, mo_coeff_tmp(ispin), opvec(1, ispin), ncol=nmo)
     386             :                CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff_tmp(ispin), opvec(1, ispin), 0.0_dp, &
     387        2782 :                                   op_fm_set(1, ispin))
     388        2782 :                CALL cp_dbcsr_sm_fm_multiply(sinmat, mo_coeff_tmp(ispin), opvec(2, ispin), ncol=nmo)
     389             :                CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff_tmp(ispin), opvec(2, ispin), 0.0_dp, &
     390        5504 :                                   op_fm_set(2, ispin))
     391             :             END DO
     392             :             !second step invert C^T S_berry C
     393        2722 :             zdet = z_one
     394        5504 :             DO ispin = 1, dft_control%nspins
     395        2782 :                CALL cp_cfm_scale_and_add_fm(z_zero, eigrmat(ispin), z_one, op_fm_set(1, ispin))
     396        2782 :                CALL cp_cfm_scale_and_add_fm(z_one, eigrmat(ispin), -gaussi, op_fm_set(2, ispin))
     397        2782 :                CALL cp_cfm_set_all(inv_mat(ispin), z_zero, z_one)
     398        2782 :                CALL cp_cfm_solve(eigrmat(ispin), inv_mat(ispin), zdeta)
     399        5504 :                zdet = zdet*zdeta
     400             :             END DO
     401        2722 :             zi(idir) = zdet**occ
     402        2722 :             ci(idir) = AIMAG(LOG(zdet**occ))
     403             : 
     404        2722 :             IF (.NOT. just_energy) THEN
     405             :                !compute the orbital derivative
     406        2550 :                focc = fpolvec(idir)
     407        5138 :                DO ispin = 1, dft_control%nspins
     408       33644 :                   inv_work(1, ispin)%local_data(:, :) = REAL(inv_mat(ispin)%local_data(:, :), dp)
     409       33644 :                   inv_work(2, ispin)%local_data(:, :) = AIMAG(inv_mat(ispin)%local_data(:, :))
     410        2588 :                   CALL get_mo_set(mo_set=mos(ispin), nao=nao, nmo=nmo)
     411             :                   CALL parallel_gemm("N", "N", nao, nmo, nmo, focc, opvec(1, ispin), inv_work(2, ispin), &
     412        2588 :                                      1.0_dp, mo_derivs_tmp(ispin))
     413             :                   CALL parallel_gemm("N", "N", nao, nmo, nmo, -focc, opvec(2, ispin), inv_work(1, ispin), &
     414        7726 :                                      1.0_dp, mo_derivs_tmp(ispin))
     415             :                END DO
     416             :             END IF
     417             : 
     418             :             !compute nuclear forces
     419        2722 :             IF (calculate_forces) THEN
     420          86 :                nkind = SIZE(qs_kind_set)
     421          86 :                natom = SIZE(particle_set)
     422         344 :                kvec(:) = twopi*cell%h_inv(idir, :)
     423             : 
     424             :                ! calculate: C [C^T S_berry C]^(-1) C^T
     425             :                ! Store this matrix in DBCSR form (only S overlap blocks)
     426         180 :                DO ispin = 1, dft_control%nspins
     427          94 :                   CALL dbcsr_set(tempmat(1, ispin)%matrix, 0.0_dp)
     428          94 :                   CALL dbcsr_set(tempmat(2, ispin)%matrix, 0.0_dp)
     429          94 :                   CALL get_mo_set(mo_set=mos(ispin), nao=nao, nmo=nmo)
     430             :                   CALL parallel_gemm("N", "N", nao, nmo, nmo, 1.0_dp, mo_coeff_tmp(ispin), inv_work(1, ispin), 0.0_dp, &
     431          94 :                                      opvec(1, ispin))
     432             :                   CALL parallel_gemm("N", "N", nao, nmo, nmo, 1.0_dp, mo_coeff_tmp(ispin), inv_work(2, ispin), 0.0_dp, &
     433          94 :                                      opvec(2, ispin))
     434             :                   CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=tempmat(1, ispin)%matrix, &
     435          94 :                                              matrix_v=opvec(1, ispin), matrix_g=mo_coeff_tmp(ispin), ncol=nmo)
     436             :                   CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=tempmat(2, ispin)%matrix, &
     437         274 :                                              matrix_v=opvec(2, ispin), matrix_g=mo_coeff_tmp(ispin), ncol=nmo)
     438             :                END DO
     439             : 
     440             :                ! Calculation of derivative integrals (da|eikr|b) and (a|eikr|db)
     441         430 :                ALLOCATE (basis_set_list(nkind))
     442         258 :                DO ikind = 1, nkind
     443         172 :                   qs_kind => qs_kind_set(ikind)
     444         172 :                   CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
     445         258 :                   IF (ASSOCIATED(basis_set_a)) THEN
     446         172 :                      basis_set_list(ikind)%gto_basis_set => basis_set_a
     447             :                   ELSE
     448           0 :                      NULLIFY (basis_set_list(ikind)%gto_basis_set)
     449             :                   END IF
     450             :                END DO
     451             :                !
     452          86 :                CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
     453        3527 :                DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     454             :                   CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, &
     455        3441 :                                          iatom=iatom, jatom=jatom, r=rab)
     456        3441 :                   basis_set_a => basis_set_list(ikind)%gto_basis_set
     457        3441 :                   IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     458        3441 :                   basis_set_b => basis_set_list(jkind)%gto_basis_set
     459        3441 :                   IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     460             :                   ! basis ikind
     461        3441 :                   first_sgfa => basis_set_a%first_sgf
     462        3441 :                   la_max => basis_set_a%lmax
     463        3441 :                   la_min => basis_set_a%lmin
     464        3441 :                   npgfa => basis_set_a%npgf
     465        3441 :                   nseta = basis_set_a%nset
     466        3441 :                   nsgfa => basis_set_a%nsgf_set
     467        3441 :                   rpgfa => basis_set_a%pgf_radius
     468        3441 :                   set_radius_a => basis_set_a%set_radius
     469        3441 :                   sphi_a => basis_set_a%sphi
     470        3441 :                   zeta => basis_set_a%zet
     471             :                   ! basis jkind
     472        3441 :                   first_sgfb => basis_set_b%first_sgf
     473        3441 :                   lb_max => basis_set_b%lmax
     474        3441 :                   lb_min => basis_set_b%lmin
     475        3441 :                   npgfb => basis_set_b%npgf
     476        3441 :                   nsetb = basis_set_b%nset
     477        3441 :                   nsgfb => basis_set_b%nsgf_set
     478        3441 :                   rpgfb => basis_set_b%pgf_radius
     479        3441 :                   set_radius_b => basis_set_b%set_radius
     480        3441 :                   sphi_b => basis_set_b%sphi
     481        3441 :                   zetb => basis_set_b%zet
     482             : 
     483        3441 :                   atom_a = atom_of_kind(iatom)
     484        3441 :                   atom_b = atom_of_kind(jatom)
     485             : 
     486        3441 :                   ldsa = SIZE(sphi_a, 1)
     487        3441 :                   ldsb = SIZE(sphi_b, 1)
     488        3441 :                   ra(:) = pbc(particle_set(iatom)%r(:), cell)
     489       13764 :                   rb(:) = ra + rab
     490        3441 :                   dab = SQRT(rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3))
     491             : 
     492        3441 :                   IF (iatom <= jatom) THEN
     493        2386 :                      irow = iatom
     494        2386 :                      icol = jatom
     495             :                   ELSE
     496        1055 :                      irow = jatom
     497        1055 :                      icol = iatom
     498             :                   END IF
     499             : 
     500        3441 :                   IF (iatom == jatom .AND. dab < 1.e-10_dp) THEN
     501             :                      fab = 1.0_dp*occ
     502             :                   ELSE
     503        3327 :                      fab = 2.0_dp*occ
     504             :                   END IF
     505             : 
     506       13764 :                   DO i = 1, 3
     507     2818179 :                      dcost(i, 1)%block = 0.0_dp
     508     2818179 :                      dsint(i, 1)%block = 0.0_dp
     509     2818179 :                      dcost(i, 2)%block = 0.0_dp
     510     2821620 :                      dsint(i, 2)%block = 0.0_dp
     511             :                   END DO
     512             : 
     513       10323 :                   DO iset = 1, nseta
     514        6882 :                      ncoa = npgfa(iset)*ncoset(la_max(iset))
     515        6882 :                      sgfa = first_sgfa(1, iset)
     516       24087 :                      DO jset = 1, nsetb
     517       13764 :                         IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
     518        6441 :                         ncob = npgfb(jset)*ncoset(lb_max(jset))
     519        6441 :                         sgfb = first_sgfb(1, jset)
     520             :                         ! Calculate the primitive integrals (da|b)
     521             :                         CALL cossin(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
     522             :                                     lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), lb_min(jset), &
     523        6441 :                                     ra, rb, kvec, cosab, sinab, dcosab, dsinab)
     524       25764 :                         DO i = 1, 3
     525             :                            CALL contract_all(dcost(i, 1)%block, dsint(i, 1)%block, &
     526             :                                              ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
     527             :                                              ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
     528       25764 :                                              dcosab(:, :, i), dsinab(:, :, i), ldab, work, ldab)
     529             :                         END DO
     530             :                         ! Calculate the primitive integrals (a|db)
     531             :                         CALL cossin(lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), lb_min(jset), &
     532             :                                     la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
     533        6441 :                                     rb, ra, kvec, cosab, sinab, dcosab, dsinab)
     534       32646 :                         DO i = 1, 3
     535     2869263 :                            dcosab(1:ncoa, 1:ncob, i) = TRANSPOSE(dcosab(1:ncob, 1:ncoa, i))
     536     2869263 :                            dsinab(1:ncoa, 1:ncob, i) = TRANSPOSE(dsinab(1:ncob, 1:ncoa, i))
     537             :                            CALL contract_all(dcost(i, 2)%block, dsint(i, 2)%block, &
     538             :                                              ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
     539             :                                              ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
     540       33087 :                                              dcosab(:, :, i), dsinab(:, :, i), ldab, work, ldab)
     541             :                         END DO
     542             :                      END DO
     543             :                   END DO
     544        3441 :                   forcea = 0.0_dp
     545        3441 :                   forceb = 0.0_dp
     546        7282 :                   DO ispin = 1, dft_control%nspins
     547        3841 :                      NULLIFY (rblock, iblock)
     548             :                      CALL dbcsr_get_block_p(matrix=tempmat(1, ispin)%matrix, &
     549        3841 :                                             row=irow, col=icol, BLOCK=rblock, found=found)
     550        3841 :                      CPASSERT(found)
     551             :                      CALL dbcsr_get_block_p(matrix=tempmat(2, ispin)%matrix, &
     552        3841 :                                             row=irow, col=icol, BLOCK=iblock, found=found)
     553        3841 :                      CPASSERT(found)
     554        3841 :                      n1 = SIZE(rblock, 1)
     555        3841 :                      n2 = SIZE(rblock, 2)
     556        3841 :                      CPASSERT(SIZE(iblock, 1) == n1)
     557        3841 :                      CPASSERT(SIZE(iblock, 2) == n2)
     558        3841 :                      CPASSERT(lsab >= n1)
     559        3841 :                      CPASSERT(lsab >= n2)
     560       14964 :                      IF (iatom <= jatom) THEN
     561       10680 :                         DO i = 1, 3
     562             :                            forcea(i) = forcea(i) + SUM(rblock(1:n1, 1:n2)*dsint(i, 1)%block(1:n1, 1:n2)) &
     563     1248306 :                                        - SUM(iblock(1:n1, 1:n2)*dcost(i, 1)%block(1:n1, 1:n2))
     564             :                            forceb(i) = forceb(i) + SUM(rblock(1:n1, 1:n2)*dsint(i, 2)%block(1:n1, 1:n2)) &
     565     1250976 :                                        - SUM(iblock(1:n1, 1:n2)*dcost(i, 2)%block(1:n1, 1:n2))
     566             :                         END DO
     567             :                      ELSE
     568        4684 :                         DO i = 1, 3
     569             :                            forcea(i) = forcea(i) + SUM(TRANSPOSE(rblock(1:n1, 1:n2))*dsint(i, 1)%block(1:n2, 1:n1)) &
     570      402645 :                                        - SUM(TRANSPOSE(iblock(1:n1, 1:n2))*dcost(i, 1)%block(1:n2, 1:n1))
     571             :                            forceb(i) = forceb(i) + SUM(TRANSPOSE(rblock(1:n1, 1:n2))*dsint(i, 2)%block(1:n2, 1:n1)) &
     572      403816 :                                        - SUM(TRANSPOSE(iblock(1:n1, 1:n2))*dcost(i, 2)%block(1:n2, 1:n1))
     573             :                         END DO
     574             :                      END IF
     575             :                   END DO
     576       13764 :                   force(ikind)%efield(1:3, atom_a) = force(ikind)%efield(1:3, atom_a) - fab*fpolvec(idir)*forcea(1:3)
     577       13764 :                   force(jkind)%efield(1:3, atom_b) = force(jkind)%efield(1:3, atom_b) - fab*fpolvec(idir)*forceb(1:3)
     578        3527 :                   IF (use_virial) THEN
     579           0 :                      f0 = -fab*fpolvec(idir)
     580           0 :                      CALL virial_pair_force(virial%pv_virial, f0, forcea, ra)
     581           0 :                      CALL virial_pair_force(virial%pv_virial, f0, forceb, rb)
     582             :                   END IF
     583             : 
     584             :                END DO
     585          86 :                CALL neighbor_list_iterator_release(nl_iterator)
     586          86 :                DEALLOCATE (basis_set_list)
     587             : 
     588             :             END IF
     589             :          END IF
     590             :       END DO
     591             : 
     592             :       ! Energy
     593        5984 :       ener_field = 0.0_dp
     594             :       ti = 0.0_dp
     595        5984 :       DO idir = 1, 3
     596             :          ! make sure the total normalized polarization is within [-1:1]
     597        4488 :          cqi(idir) = qi(idir) + ci(idir)
     598        4488 :          IF (cqi(idir) > pi) cqi(idir) = cqi(idir) - twopi
     599        4488 :          IF (cqi(idir) < -pi) cqi(idir) = cqi(idir) + twopi
     600             :          ! now check for log branch
     601        4488 :          IF (ABS(efield%polarisation(idir) - cqi(idir)) > pi) THEN
     602           0 :             ti(idir) = (efield%polarisation(idir) - cqi(idir))/pi
     603           0 :             DO i = 1, 10
     604           0 :                cqi(idir) = cqi(idir) + SIGN(1.0_dp, ti(idir))*twopi
     605           0 :                IF (ABS(efield%polarisation(idir) - cqi(idir)) < pi) EXIT
     606             :             END DO
     607             :          END IF
     608        5984 :          ener_field = ener_field + fpolvec(idir)*cqi(idir)
     609             :       END DO
     610             : 
     611             :       ! update the references
     612        1496 :       IF (calculate_forces) THEN
     613             :          ! check for smoothness of energy surface
     614         304 :          IF (ABS(efield%field_energy - ener_field) > pi*ABS(SUM(fpolvec))) THEN
     615           8 :             CPWARN("Large change of e-field energy detected. Correct for non-smooth energy surface")
     616             :          END IF
     617          76 :          efield%field_energy = ener_field
     618         304 :          efield%polarisation(:) = cqi(:)
     619             :       END IF
     620        1496 :       energy%efield = ener_field
     621             : 
     622        1496 :       IF (.NOT. just_energy) THEN
     623             :          ! Add the result to mo_derivativs
     624        2638 :          DO ispin = 1, dft_control%nspins
     625        2638 :             CALL copy_fm_to_dbcsr(mo_derivs_tmp(ispin), mo_derivs(ispin)%matrix)
     626             :          END DO
     627        1300 :          IF (use_virial) THEN
     628           0 :             ti = 0.0_dp
     629           0 :             DO i = 1, 3
     630           0 :                DO j = 1, 3
     631           0 :                   ti(j) = ti(j) + hmat(j, i)*cqi(i)
     632             :                END DO
     633             :             END DO
     634           0 :             DO i = 1, 3
     635           0 :                DO j = 1, 3
     636           0 :                   virial%pv_virial(i, j) = virial%pv_virial(i, j) - fieldpol(i)*ti(j)
     637             :                END DO
     638             :             END DO
     639             :          END IF
     640             :       END IF
     641             : 
     642        3052 :       DO ispin = 1, dft_control%nspins
     643        1556 :          CALL cp_cfm_release(eigrmat(ispin))
     644        1556 :          CALL cp_cfm_release(inv_mat(ispin))
     645        1556 :          CALL cp_fm_release(mo_derivs_tmp(ispin))
     646        1556 :          IF (mos(ispin)%use_mo_coeff_b) CALL cp_fm_release(mo_coeff_tmp(ispin))
     647        6164 :          DO i = 1, SIZE(op_fm_set, 1)
     648        3112 :             CALL cp_fm_release(opvec(i, ispin))
     649        3112 :             CALL cp_fm_release(op_fm_set(i, ispin))
     650        4668 :             CALL cp_fm_release(inv_work(i, ispin))
     651             :          END DO
     652             :       END DO
     653        1496 :       DEALLOCATE (inv_mat, inv_work, op_fm_set, opvec, eigrmat)
     654        1496 :       DEALLOCATE (mo_coeff_tmp, mo_derivs_tmp)
     655             : 
     656        1496 :       IF (calculate_forces) THEN
     657         228 :          DO ikind = 1, SIZE(atomic_kind_set)
     658        1972 :             CALL para_env%sum(force(ikind)%efield)
     659             :          END DO
     660          76 :          DEALLOCATE (cosab, sinab, work, dcosab, dsinab)
     661         304 :          DO i = 1, 3
     662         228 :             DEALLOCATE (dcost(i, 1)%block, dsint(i, 1)%block)
     663         304 :             DEALLOCATE (dcost(i, 2)%block, dsint(i, 2)%block)
     664             :          END DO
     665          76 :          CALL dbcsr_deallocate_matrix_set(tempmat)
     666             :       END IF
     667        1496 :       CALL timestop(handle)
     668             : 
     669        5984 :    END SUBROUTINE qs_efield_derivatives
     670             : 
     671             : ! **************************************************************************************************
     672             : !> \brief ...
     673             : !> \param qs_env ...
     674             : !> \param just_energy ...
     675             : !> \param calculate_forces ...
     676             : ! **************************************************************************************************
     677         898 :    SUBROUTINE qs_dispfield_derivatives(qs_env, just_energy, calculate_forces)
     678             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     679             :       LOGICAL, INTENT(IN)                                :: just_energy, calculate_forces
     680             : 
     681             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_dispfield_derivatives'
     682             : 
     683             :       COMPLEX(dp)                                        :: zdet, zdeta, zi(3)
     684             :       INTEGER :: handle, i, ia, iatom, icol, idir, ikind, iodeb, irow, iset, ispin, jatom, jkind, &
     685             :          jset, ldab, ldsa, ldsb, lsab, n1, n2, nao, natom, ncoa, ncob, nkind, nmo, nseta, nsetb, &
     686             :          sgfa, sgfb
     687         898 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind
     688         898 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
     689         898 :                                                             npgfb, nsgfa, nsgfb
     690         898 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
     691             :       LOGICAL                                            :: found, uniform, use_virial
     692             :       REAL(dp) :: charge, ci(3), cqi(3), dab, dd, di(3), ener_field, fab, fieldpol(3), focc, &
     693             :          hmat(3, 3), occ, omega, qi(3), rlog(3), strength, zlog(3)
     694             :       REAL(dp), DIMENSION(3)                             :: dfilter, forcea, forceb, kvec, ra, rab, &
     695             :                                                             rb, ria
     696        1796 :       REAL(dp), DIMENSION(:, :), POINTER                 :: cosab, iblock, rblock, sinab, work
     697        2694 :       REAL(dp), DIMENSION(:, :, :), POINTER              :: dcosab, dsinab, force_tmp
     698         898 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
     699         898 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb
     700         898 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     701       16164 :       TYPE(block_p_type), DIMENSION(3, 2)                :: dcost, dsint
     702             :       TYPE(cell_type), POINTER                           :: cell
     703         898 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: eigrmat, inv_mat
     704             :       TYPE(cp_fm_struct_type), POINTER                   :: tmp_fm_struct
     705         898 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: mo_coeff_tmp
     706         898 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: inv_work, mo_derivs_tmp, op_fm_set, opvec
     707             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     708         898 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, mo_derivs
     709         898 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: tempmat
     710             :       TYPE(dbcsr_type), POINTER                          :: cosmat, mo_coeff_b, sinmat
     711             :       TYPE(dft_control_type), POINTER                    :: dft_control
     712             :       TYPE(efield_berry_type), POINTER                   :: efield
     713         898 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     714             :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     715         898 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     716             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     717             :       TYPE(neighbor_list_iterator_p_type), &
     718         898 :          DIMENSION(:), POINTER                           :: nl_iterator
     719             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     720         898 :          POINTER                                         :: sab_orb
     721         898 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     722             :       TYPE(qs_energy_type), POINTER                      :: energy
     723         898 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
     724         898 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     725             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     726             :       TYPE(virial_type), POINTER                         :: virial
     727             : 
     728         898 :       CALL timeset(routineN, handle)
     729             : 
     730         898 :       NULLIFY (dft_control, cell, particle_set)
     731             :       CALL get_qs_env(qs_env, dft_control=dft_control, cell=cell, &
     732         898 :                       particle_set=particle_set, virial=virial)
     733         898 :       NULLIFY (qs_kind_set, efield, para_env, sab_orb)
     734             :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
     735         898 :                       efield=efield, energy=energy, para_env=para_env, sab_orb=sab_orb)
     736             : 
     737             :       ! calculate stress only if forces requested also
     738         898 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
     739           0 :       use_virial = use_virial .AND. calculate_forces
     740             :       ! disable stress calculation
     741             :       IF (use_virial) THEN
     742           0 :          CPABORT("Stress tensor for periodic D-field not implemented")
     743             :       END IF
     744             : 
     745        3592 :       dfilter(1:3) = dft_control%period_efield%d_filter(1:3)
     746             : 
     747             :       ! if an intensities list is given, select the value for the current step
     748         898 :       strength = dft_control%period_efield%strength
     749         898 :       IF (ALLOCATED(dft_control%period_efield%strength_list)) THEN
     750             :          strength = dft_control%period_efield%strength_list(MOD(qs_env%sim_step &
     751           0 :                                         - dft_control%period_efield%start_frame, SIZE(dft_control%period_efield%strength_list)) + 1)
     752             :       END IF
     753             : 
     754        3592 :       fieldpol = dft_control%period_efield%polarisation
     755        6286 :       fieldpol = fieldpol/SQRT(DOT_PRODUCT(fieldpol, fieldpol))
     756        3592 :       fieldpol = fieldpol*strength
     757             : 
     758         898 :       omega = cell%deth
     759       11674 :       hmat = cell%hmat(:, :)/(twopi*omega)
     760             : 
     761             :       ! nuclear contribution to polarization
     762         898 :       natom = SIZE(particle_set)
     763         898 :       IF (calculate_forces) THEN
     764          10 :          CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, force=force)
     765          10 :          CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind)
     766          40 :          ALLOCATE (force_tmp(natom, 3, 3))
     767         310 :          force_tmp = 0.0_dp
     768             :       END IF
     769        3592 :       zi(:) = CMPLX(1._dp, 0._dp, dp)
     770        2694 :       DO ia = 1, natom
     771        1796 :          CALL get_atomic_kind(particle_set(ia)%atomic_kind, kind_number=ikind)
     772        1796 :          CALL get_qs_kind(qs_kind_set(ikind), core_charge=charge)
     773        7184 :          ria = particle_set(ia)%r
     774        7184 :          ria = pbc(ria, cell)
     775        7184 :          DO idir = 1, 3
     776       21552 :             kvec(:) = twopi*cell%h_inv(idir, :)
     777       21552 :             dd = SUM(kvec(:)*ria(:))
     778        5388 :             zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)**charge
     779        7184 :             zi(idir) = zi(idir)*zdeta
     780             :          END DO
     781        4490 :          IF (calculate_forces) THEN
     782          20 :             IF (para_env%mepos == 0) THEN
     783          40 :                DO i = 1, 3
     784          40 :                   force_tmp(ia, i, i) = force_tmp(ia, i, i) + charge/omega
     785             :                END DO
     786             :             END IF
     787             :          END IF
     788             :       END DO
     789        3592 :       rlog = AIMAG(LOG(zi))
     790             : 
     791             :       ! check uniform occupation
     792         898 :       NULLIFY (mos)
     793         898 :       CALL get_qs_env(qs_env=qs_env, mos=mos)
     794        1796 :       DO ispin = 1, dft_control%nspins
     795         898 :          CALL get_mo_set(mo_set=mos(ispin), maxocc=occ, uniform_occupation=uniform)
     796        1796 :          IF (.NOT. uniform) THEN
     797           0 :             CPABORT("Berry phase moments for non uniform MO occupation numbers not implemented")
     798             :          END IF
     799             :       END DO
     800             : 
     801             :       ! initialize all work matrices needed
     802         898 :       NULLIFY (mo_derivs)
     803         898 :       CALL get_qs_env(qs_env=qs_env, mo_derivs=mo_derivs)
     804        5388 :       ALLOCATE (op_fm_set(2, dft_control%nspins))
     805        5388 :       ALLOCATE (opvec(2, dft_control%nspins))
     806        3592 :       ALLOCATE (eigrmat(dft_control%nspins))
     807        3592 :       ALLOCATE (inv_mat(dft_control%nspins))
     808        5388 :       ALLOCATE (inv_work(2, dft_control%nspins))
     809        6286 :       ALLOCATE (mo_derivs_tmp(3, SIZE(mo_derivs)))
     810        3592 :       ALLOCATE (mo_coeff_tmp(SIZE(mo_derivs)))
     811             : 
     812             :       ! Allocate temp matrices for the wavefunction derivatives
     813        1796 :       DO ispin = 1, dft_control%nspins
     814         898 :          NULLIFY (tmp_fm_struct, mo_coeff)
     815         898 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nao=nao, nmo=nmo)
     816             :          CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=nmo, &
     817         898 :                                   ncol_global=nmo, para_env=para_env, context=mo_coeff%matrix_struct%context)
     818         898 :          CALL cp_fm_create(mo_coeff_tmp(ispin), mo_coeff%matrix_struct)
     819        3592 :          DO i = 1, 3
     820        2694 :             CALL cp_fm_create(mo_derivs_tmp(i, ispin), mo_coeff%matrix_struct)
     821        3592 :             CALL cp_fm_set_all(matrix=mo_derivs_tmp(i, ispin), alpha=0.0_dp)
     822             :          END DO
     823        2694 :          DO i = 1, SIZE(op_fm_set, 1)
     824        1796 :             CALL cp_fm_create(opvec(i, ispin), mo_coeff%matrix_struct)
     825        1796 :             CALL cp_fm_create(op_fm_set(i, ispin), tmp_fm_struct)
     826        2694 :             CALL cp_fm_create(inv_work(i, ispin), op_fm_set(i, ispin)%matrix_struct)
     827             :          END DO
     828         898 :          CALL cp_cfm_create(eigrmat(ispin), op_fm_set(1, ispin)%matrix_struct)
     829         898 :          CALL cp_cfm_create(inv_mat(ispin), op_fm_set(1, ispin)%matrix_struct)
     830        2694 :          CALL cp_fm_struct_release(tmp_fm_struct)
     831             :       END DO
     832             :       ! temp matrices for force calculation
     833         898 :       IF (calculate_forces) THEN
     834          10 :          NULLIFY (matrix_s)
     835          10 :          CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s)
     836          60 :          ALLOCATE (tempmat(2, dft_control%nspins))
     837          20 :          DO ispin = 1, dft_control%nspins
     838          10 :             ALLOCATE (tempmat(1, ispin)%matrix, tempmat(2, ispin)%matrix)
     839          10 :             CALL dbcsr_copy(tempmat(1, ispin)%matrix, matrix_s(1)%matrix, 'TEMPMAT')
     840          10 :             CALL dbcsr_copy(tempmat(2, ispin)%matrix, matrix_s(1)%matrix, 'TEMPMAT')
     841          10 :             CALL dbcsr_set(tempmat(1, ispin)%matrix, 0.0_dp)
     842          20 :             CALL dbcsr_set(tempmat(2, ispin)%matrix, 0.0_dp)
     843             :          END DO
     844             :          ! integration
     845          10 :          CALL get_qs_kind_set(qs_kind_set, maxco=ldab, maxsgf=lsab)
     846          80 :          ALLOCATE (cosab(ldab, ldab), sinab(ldab, ldab), work(ldab, ldab))
     847          70 :          ALLOCATE (dcosab(ldab, ldab, 3), dsinab(ldab, ldab, 3))
     848          10 :          lsab = MAX(lsab, ldab)
     849          50 :          DO i = 1, 3
     850         180 :             ALLOCATE (dcost(i, 1)%block(lsab, lsab), dsint(i, 1)%block(lsab, lsab))
     851         160 :             ALLOCATE (dcost(i, 2)%block(lsab, lsab), dsint(i, 2)%block(lsab, lsab))
     852             :          END DO
     853             :       END IF
     854             : 
     855             :       !Start the MO derivative calculation
     856             :       !loop over all cell vectors
     857        3592 :       DO idir = 1, 3
     858        2694 :          zi(idir) = z_zero
     859        2694 :          cosmat => efield%cosmat(idir)%matrix
     860        2694 :          sinmat => efield%sinmat(idir)%matrix
     861             :          !evaluate the expression needed for the derivative (S_berry * C  and [C^T S_berry C]^-1)
     862             :          !first step S_berry * C  and C^T S_berry C
     863        5388 :          DO ispin = 1, dft_control%nspins ! spin
     864        2694 :             IF (mos(ispin)%use_mo_coeff_b) THEN
     865        2694 :                CALL get_mo_set(mo_set=mos(ispin), nao=nao, mo_coeff_b=mo_coeff_b, nmo=nmo)
     866        2694 :                CALL copy_dbcsr_to_fm(mo_coeff_b, mo_coeff_tmp(ispin))
     867             :             ELSE
     868           0 :                CALL get_mo_set(mo_set=mos(ispin), nao=nao, mo_coeff=mo_coeff, nmo=nmo)
     869           0 :                mo_coeff_tmp(ispin) = mo_coeff
     870             :             END IF
     871        2694 :             CALL cp_dbcsr_sm_fm_multiply(cosmat, mo_coeff_tmp(ispin), opvec(1, ispin), ncol=nmo)
     872             :             CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff_tmp(ispin), opvec(1, ispin), 0.0_dp, &
     873        2694 :                                op_fm_set(1, ispin))
     874        2694 :             CALL cp_dbcsr_sm_fm_multiply(sinmat, mo_coeff_tmp(ispin), opvec(2, ispin), ncol=nmo)
     875             :             CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff_tmp(ispin), opvec(2, ispin), 0.0_dp, &
     876        5388 :                                op_fm_set(2, ispin))
     877             :          END DO
     878             :          !second step invert C^T S_berry C
     879        2694 :          zdet = z_one
     880        5388 :          DO ispin = 1, dft_control%nspins
     881        2694 :             CALL cp_cfm_scale_and_add_fm(z_zero, eigrmat(ispin), z_one, op_fm_set(1, ispin))
     882        2694 :             CALL cp_cfm_scale_and_add_fm(z_one, eigrmat(ispin), -gaussi, op_fm_set(2, ispin))
     883        2694 :             CALL cp_cfm_set_all(inv_mat(ispin), z_zero, z_one)
     884        2694 :             CALL cp_cfm_solve(eigrmat(ispin), inv_mat(ispin), zdeta)
     885        5388 :             zdet = zdet*zdeta
     886             :          END DO
     887        2694 :          zi(idir) = zdet**occ
     888        2694 :          zlog(idir) = AIMAG(LOG(zi(idir)))
     889             : 
     890        2694 :          IF (.NOT. just_energy) THEN
     891             :             !compute the orbital derivative
     892        5388 :             DO ispin = 1, dft_control%nspins
     893       35022 :                inv_work(1, ispin)%local_data(:, :) = REAL(inv_mat(ispin)%local_data(:, :), dp)
     894       35022 :                inv_work(2, ispin)%local_data(:, :) = AIMAG(inv_mat(ispin)%local_data(:, :))
     895        2694 :                CALL get_mo_set(mo_set=mos(ispin), nao=nao, nmo=nmo)
     896       13470 :                DO i = 1, 3
     897        8082 :                   focc = hmat(idir, i)
     898             :                   CALL parallel_gemm("N", "N", nao, nmo, nmo, focc, opvec(1, ispin), inv_work(2, ispin), &
     899        8082 :                                      1.0_dp, mo_derivs_tmp(idir, ispin))
     900             :                   CALL parallel_gemm("N", "N", nao, nmo, nmo, -focc, opvec(2, ispin), inv_work(1, ispin), &
     901       10776 :                                      1.0_dp, mo_derivs_tmp(idir, ispin))
     902             :                END DO
     903             :             END DO
     904             :          END IF
     905             : 
     906             :          !compute nuclear forces
     907        3592 :          IF (calculate_forces) THEN
     908          30 :             nkind = SIZE(qs_kind_set)
     909          30 :             natom = SIZE(particle_set)
     910         120 :             kvec(:) = twopi*cell%h_inv(idir, :)
     911             : 
     912             :             ! calculate: C [C^T S_berry C]^(-1) C^T
     913             :             ! Store this matrix in DBCSR form (only S overlap blocks)
     914          60 :             DO ispin = 1, dft_control%nspins
     915          30 :                CALL dbcsr_set(tempmat(1, ispin)%matrix, 0.0_dp)
     916          30 :                CALL dbcsr_set(tempmat(2, ispin)%matrix, 0.0_dp)
     917          30 :                CALL get_mo_set(mo_set=mos(ispin), nao=nao, nmo=nmo)
     918             :                CALL parallel_gemm("N", "N", nao, nmo, nmo, 1.0_dp, mo_coeff_tmp(ispin), inv_work(1, ispin), 0.0_dp, &
     919          30 :                                   opvec(1, ispin))
     920             :                CALL parallel_gemm("N", "N", nao, nmo, nmo, 1.0_dp, mo_coeff_tmp(ispin), inv_work(2, ispin), 0.0_dp, &
     921          30 :                                   opvec(2, ispin))
     922             :                CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=tempmat(1, ispin)%matrix, &
     923          30 :                                           matrix_v=opvec(1, ispin), matrix_g=mo_coeff_tmp(ispin), ncol=nmo)
     924             :                CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=tempmat(2, ispin)%matrix, &
     925          90 :                                           matrix_v=opvec(2, ispin), matrix_g=mo_coeff_tmp(ispin), ncol=nmo)
     926             :             END DO
     927             : 
     928             :             ! Calculation of derivative integrals (da|eikr|b) and (a|eikr|db)
     929         150 :             ALLOCATE (basis_set_list(nkind))
     930          90 :             DO ikind = 1, nkind
     931          60 :                qs_kind => qs_kind_set(ikind)
     932          60 :                CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
     933          90 :                IF (ASSOCIATED(basis_set_a)) THEN
     934          60 :                   basis_set_list(ikind)%gto_basis_set => basis_set_a
     935             :                ELSE
     936           0 :                   NULLIFY (basis_set_list(ikind)%gto_basis_set)
     937             :                END IF
     938             :             END DO
     939             :             !
     940          30 :             CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
     941         585 :             DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     942             :                CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, &
     943         555 :                                       iatom=iatom, jatom=jatom, r=rab)
     944         555 :                basis_set_a => basis_set_list(ikind)%gto_basis_set
     945         555 :                IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     946         555 :                basis_set_b => basis_set_list(jkind)%gto_basis_set
     947         555 :                IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     948             :                ! basis ikind
     949         555 :                first_sgfa => basis_set_a%first_sgf
     950         555 :                la_max => basis_set_a%lmax
     951         555 :                la_min => basis_set_a%lmin
     952         555 :                npgfa => basis_set_a%npgf
     953         555 :                nseta = basis_set_a%nset
     954         555 :                nsgfa => basis_set_a%nsgf_set
     955         555 :                rpgfa => basis_set_a%pgf_radius
     956         555 :                set_radius_a => basis_set_a%set_radius
     957         555 :                sphi_a => basis_set_a%sphi
     958         555 :                zeta => basis_set_a%zet
     959             :                ! basis jkind
     960         555 :                first_sgfb => basis_set_b%first_sgf
     961         555 :                lb_max => basis_set_b%lmax
     962         555 :                lb_min => basis_set_b%lmin
     963         555 :                npgfb => basis_set_b%npgf
     964         555 :                nsetb = basis_set_b%nset
     965         555 :                nsgfb => basis_set_b%nsgf_set
     966         555 :                rpgfb => basis_set_b%pgf_radius
     967         555 :                set_radius_b => basis_set_b%set_radius
     968         555 :                sphi_b => basis_set_b%sphi
     969         555 :                zetb => basis_set_b%zet
     970             : 
     971         555 :                ldsa = SIZE(sphi_a, 1)
     972         555 :                ldsb = SIZE(sphi_b, 1)
     973         555 :                ra(:) = pbc(particle_set(iatom)%r(:), cell)
     974        2220 :                rb(:) = ra + rab
     975         555 :                dab = SQRT(rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3))
     976             : 
     977         555 :                IF (iatom <= jatom) THEN
     978         354 :                   irow = iatom
     979         354 :                   icol = jatom
     980             :                ELSE
     981         201 :                   irow = jatom
     982         201 :                   icol = iatom
     983             :                END IF
     984             : 
     985         555 :                IF (iatom == jatom .AND. dab < 1.e-10_dp) THEN
     986             :                   fab = 1.0_dp*occ
     987             :                ELSE
     988         525 :                   fab = 2.0_dp*occ
     989             :                END IF
     990             : 
     991        2220 :                DO i = 1, 3
     992      454545 :                   dcost(i, 1)%block = 0.0_dp
     993      454545 :                   dsint(i, 1)%block = 0.0_dp
     994      454545 :                   dcost(i, 2)%block = 0.0_dp
     995      455100 :                   dsint(i, 2)%block = 0.0_dp
     996             :                END DO
     997             : 
     998        1665 :                DO iset = 1, nseta
     999        1110 :                   ncoa = npgfa(iset)*ncoset(la_max(iset))
    1000        1110 :                   sgfa = first_sgfa(1, iset)
    1001        3885 :                   DO jset = 1, nsetb
    1002        2220 :                      IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
    1003        1140 :                      ncob = npgfb(jset)*ncoset(lb_max(jset))
    1004        1140 :                      sgfb = first_sgfb(1, jset)
    1005             :                      ! Calculate the primitive integrals (da|b)
    1006             :                      CALL cossin(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
    1007             :                                  lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), lb_min(jset), &
    1008        1140 :                                  ra, rb, kvec, cosab, sinab, dcosab, dsinab)
    1009        4560 :                      DO i = 1, 3
    1010             :                         CALL contract_all(dcost(i, 1)%block, dsint(i, 1)%block, &
    1011             :                                           ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
    1012             :                                           ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
    1013        4560 :                                           dcosab(:, :, i), dsinab(:, :, i), ldab, work, ldab)
    1014             :                      END DO
    1015             :                      ! Calculate the primitive integrals (a|db)
    1016             :                      CALL cossin(lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), lb_min(jset), &
    1017             :                                  la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
    1018        1140 :                                  rb, ra, kvec, cosab, sinab, dcosab, dsinab)
    1019        5670 :                      DO i = 1, 3
    1020      560556 :                         dcosab(1:ncoa, 1:ncob, i) = TRANSPOSE(dcosab(1:ncob, 1:ncoa, i))
    1021      560556 :                         dsinab(1:ncoa, 1:ncob, i) = TRANSPOSE(dsinab(1:ncob, 1:ncoa, i))
    1022             :                         CALL contract_all(dcost(i, 2)%block, dsint(i, 2)%block, &
    1023             :                                           ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
    1024             :                                           ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
    1025        5640 :                                           dcosab(:, :, i), dsinab(:, :, i), ldab, work, ldab)
    1026             :                      END DO
    1027             :                   END DO
    1028             :                END DO
    1029         555 :                forcea = 0.0_dp
    1030         555 :                forceb = 0.0_dp
    1031        1110 :                DO ispin = 1, dft_control%nspins
    1032         555 :                   NULLIFY (rblock, iblock)
    1033             :                   CALL dbcsr_get_block_p(matrix=tempmat(1, ispin)%matrix, &
    1034         555 :                                          row=irow, col=icol, BLOCK=rblock, found=found)
    1035         555 :                   CPASSERT(found)
    1036             :                   CALL dbcsr_get_block_p(matrix=tempmat(2, ispin)%matrix, &
    1037         555 :                                          row=irow, col=icol, BLOCK=iblock, found=found)
    1038         555 :                   CPASSERT(found)
    1039         555 :                   n1 = SIZE(rblock, 1)
    1040         555 :                   n2 = SIZE(rblock, 2)
    1041         555 :                   CPASSERT(SIZE(iblock, 1) == n1)
    1042         555 :                   CPASSERT(SIZE(iblock, 2) == n2)
    1043         555 :                   CPASSERT(lsab >= n1)
    1044         555 :                   CPASSERT(lsab >= n2)
    1045        2220 :                   IF (iatom <= jatom) THEN
    1046        1416 :                      DO i = 1, 3
    1047             :                         forcea(i) = forcea(i) + SUM(rblock(1:n1, 1:n2)*dsint(i, 1)%block(1:n1, 1:n2)) &
    1048      160542 :                                     - SUM(iblock(1:n1, 1:n2)*dcost(i, 1)%block(1:n1, 1:n2))
    1049             :                         forceb(i) = forceb(i) + SUM(rblock(1:n1, 1:n2)*dsint(i, 2)%block(1:n1, 1:n2)) &
    1050      160896 :                                     - SUM(iblock(1:n1, 1:n2)*dcost(i, 2)%block(1:n1, 1:n2))
    1051             :                      END DO
    1052             :                   ELSE
    1053         804 :                      DO i = 1, 3
    1054             :                         forcea(i) = forcea(i) + SUM(TRANSPOSE(rblock(1:n1, 1:n2))*dsint(i, 1)%block(1:n2, 1:n1)) &
    1055       85023 :                                     - SUM(TRANSPOSE(iblock(1:n1, 1:n2))*dcost(i, 1)%block(1:n2, 1:n1))
    1056             :                         forceb(i) = forceb(i) + SUM(TRANSPOSE(rblock(1:n1, 1:n2))*dsint(i, 2)%block(1:n2, 1:n1)) &
    1057       85224 :                                     - SUM(TRANSPOSE(iblock(1:n1, 1:n2))*dcost(i, 2)%block(1:n2, 1:n1))
    1058             :                      END DO
    1059             :                   END IF
    1060             :                END DO
    1061        2250 :                DO i = 1, 3
    1062        6660 :                   force_tmp(iatom, :, i) = force_tmp(iatom, :, i) - fab*hmat(i, idir)*forcea(:)
    1063        7215 :                   force_tmp(jatom, :, i) = force_tmp(jatom, :, i) - fab*hmat(i, idir)*forceb(:)
    1064             :                END DO
    1065             :             END DO
    1066          30 :             CALL neighbor_list_iterator_release(nl_iterator)
    1067          30 :             DEALLOCATE (basis_set_list)
    1068             :          END IF
    1069             :       END DO
    1070             : 
    1071             :       ! make sure the total normalized polarization is within [-1:1]
    1072        3592 :       DO idir = 1, 3
    1073        2694 :          cqi(idir) = rlog(idir) + zlog(idir)
    1074        2694 :          IF (cqi(idir) > pi) cqi(idir) = cqi(idir) - twopi
    1075        2694 :          IF (cqi(idir) < -pi) cqi(idir) = cqi(idir) + twopi
    1076             :          ! now check for log branch
    1077        3592 :          IF (calculate_forces) THEN
    1078          30 :             IF (ABS(efield%polarisation(idir) - cqi(idir)) > pi) THEN
    1079           0 :                di(idir) = (efield%polarisation(idir) - cqi(idir))/pi
    1080           0 :                DO i = 1, 10
    1081           0 :                   cqi(idir) = cqi(idir) + SIGN(1.0_dp, di(idir))*twopi
    1082           0 :                   IF (ABS(efield%polarisation(idir) - cqi(idir)) < pi) EXIT
    1083             :                END DO
    1084             :             END IF
    1085             :          END IF
    1086             :       END DO
    1087        3592 :       DO idir = 1, 3
    1088        2694 :          qi(idir) = 0.0_dp
    1089        2694 :          ci(idir) = 0.0_dp
    1090       11674 :          DO i = 1, 3
    1091       10776 :             ci(idir) = ci(idir) + hmat(idir, i)*cqi(i)
    1092             :          END DO
    1093             :       END DO
    1094             : 
    1095             :       ! update the references
    1096         898 :       IF (calculate_forces) THEN
    1097          40 :          ener_field = SUM(ci)
    1098             :          ! check for smoothness of energy surface
    1099         130 :          IF (ABS(efield%field_energy - ener_field) > pi*ABS(SUM(hmat))) THEN
    1100           0 :             CPWARN("Large change of e-field energy detected. Correct for non-smooth energy surface")
    1101             :          END IF
    1102          10 :          efield%field_energy = ener_field
    1103          40 :          efield%polarisation(:) = cqi(:)
    1104             :       END IF
    1105             : 
    1106             :       ! Energy
    1107         898 :       ener_field = 0.0_dp
    1108        3592 :       DO i = 1, 3
    1109        3592 :          ener_field = ener_field + dfilter(i)*(fieldpol(i) - 2._dp*twopi*ci(i))**2
    1110             :       END DO
    1111         898 :       energy%efield = 0.25_dp*omega/twopi*ener_field
    1112             : 
    1113             :       ! debugging output
    1114             :       IF (para_env%is_source()) THEN
    1115         898 :          iodeb = -1
    1116             :          IF (iodeb > 0) THEN
    1117             :             WRITE (iodeb, '(A,T61,F20.10)') "  Polarisation Quantum:  ", 2._dp*twopi*twopi*hmat(3, 3)
    1118             :             WRITE (iodeb, '(A,T21,3F20.10)') "  Polarisation: ", 2._dp*twopi*ci(1:3)
    1119             :             WRITE (iodeb, '(A,T21,3F20.10)') "  Displacement: ", fieldpol(1:3)
    1120             :             WRITE (iodeb, '(A,T21,3F20.10)') "  E-Field:      ", ((fieldpol(i) - 2._dp*twopi*ci(i)), i=1, 3)
    1121             :             WRITE (iodeb, '(A,T61,F20.10)') "  Disp Free Energy:", energy%efield
    1122             :          END IF
    1123             :       END IF
    1124             : 
    1125         898 :       IF (.NOT. just_energy) THEN
    1126        3592 :          DO i = 1, 3
    1127        3592 :             di(i) = -omega*(fieldpol(i) - 2._dp*twopi*ci(i))*dfilter(i)
    1128             :          END DO
    1129             :          ! Add the result to mo_derivativs
    1130        1796 :          DO ispin = 1, dft_control%nspins
    1131         898 :             CALL copy_dbcsr_to_fm(mo_derivs(ispin)%matrix, mo_coeff_tmp(ispin))
    1132        4490 :             DO idir = 1, 3
    1133             :                CALL cp_fm_scale_and_add(1.0_dp, mo_coeff_tmp(ispin), di(idir), &
    1134        3592 :                                         mo_derivs_tmp(idir, ispin))
    1135             :             END DO
    1136             :          END DO
    1137        1796 :          DO ispin = 1, dft_control%nspins
    1138        1796 :             CALL copy_fm_to_dbcsr(mo_coeff_tmp(ispin), mo_derivs(ispin)%matrix)
    1139             :          END DO
    1140             :       END IF
    1141             : 
    1142         898 :       IF (calculate_forces) THEN
    1143          40 :          DO i = 1, 3
    1144         100 :             DO ia = 1, natom
    1145          60 :                CALL get_atomic_kind(particle_set(ia)%atomic_kind, kind_number=ikind)
    1146          60 :                iatom = atom_of_kind(ia)
    1147         450 :                force(ikind)%efield(1:3, iatom) = force(ikind)%efield(1:3, iatom) + di(i)*force_tmp(ia, 1:3, i)
    1148             :             END DO
    1149             :          END DO
    1150             :       END IF
    1151             : 
    1152        1796 :       DO ispin = 1, dft_control%nspins
    1153         898 :          CALL cp_cfm_release(eigrmat(ispin))
    1154         898 :          CALL cp_cfm_release(inv_mat(ispin))
    1155         898 :          IF (mos(ispin)%use_mo_coeff_b) CALL cp_fm_release(mo_coeff_tmp(ispin))
    1156        3592 :          DO i = 1, 3
    1157        3592 :             CALL cp_fm_release(mo_derivs_tmp(i, ispin))
    1158             :          END DO
    1159        3592 :          DO i = 1, SIZE(op_fm_set, 1)
    1160        1796 :             CALL cp_fm_release(opvec(i, ispin))
    1161        1796 :             CALL cp_fm_release(op_fm_set(i, ispin))
    1162        2694 :             CALL cp_fm_release(inv_work(i, ispin))
    1163             :          END DO
    1164             :       END DO
    1165         898 :       DEALLOCATE (inv_mat, inv_work, op_fm_set, opvec, eigrmat)
    1166         898 :       DEALLOCATE (mo_coeff_tmp, mo_derivs_tmp)
    1167             : 
    1168         898 :       IF (calculate_forces) THEN
    1169          30 :          DO ikind = 1, SIZE(atomic_kind_set)
    1170         190 :             CALL para_env%sum(force(ikind)%efield)
    1171             :          END DO
    1172          10 :          DEALLOCATE (force_tmp)
    1173          10 :          DEALLOCATE (cosab, sinab, work, dcosab, dsinab)
    1174          40 :          DO i = 1, 3
    1175          30 :             DEALLOCATE (dcost(i, 1)%block, dsint(i, 1)%block)
    1176          40 :             DEALLOCATE (dcost(i, 2)%block, dsint(i, 2)%block)
    1177             :          END DO
    1178          10 :          CALL dbcsr_deallocate_matrix_set(tempmat)
    1179             :       END IF
    1180         898 :       CALL timestop(handle)
    1181             : 
    1182        3592 :    END SUBROUTINE qs_dispfield_derivatives
    1183             : 
    1184             : ! **************************************************************************************************
    1185             : !> \brief ...
    1186             : !> \param cos_block ...
    1187             : !> \param sin_block ...
    1188             : !> \param ncoa ...
    1189             : !> \param nsgfa ...
    1190             : !> \param sgfa ...
    1191             : !> \param sphi_a ...
    1192             : !> \param ldsa ...
    1193             : !> \param ncob ...
    1194             : !> \param nsgfb ...
    1195             : !> \param sgfb ...
    1196             : !> \param sphi_b ...
    1197             : !> \param ldsb ...
    1198             : !> \param cosab ...
    1199             : !> \param sinab ...
    1200             : !> \param ldab ...
    1201             : !> \param work ...
    1202             : !> \param ldwork ...
    1203             : ! **************************************************************************************************
    1204       45486 :    SUBROUTINE contract_all(cos_block, sin_block, &
    1205       90972 :                            ncoa, nsgfa, sgfa, sphi_a, ldsa, &
    1206       90972 :                            ncob, nsgfb, sgfb, sphi_b, ldsb, &
    1207       45486 :                            cosab, sinab, ldab, work, ldwork)
    1208             : 
    1209             :       REAL(dp), DIMENSION(:, :), POINTER                 :: cos_block, sin_block
    1210             :       INTEGER, INTENT(IN)                                :: ncoa, nsgfa, sgfa
    1211             :       REAL(dp), DIMENSION(:, :), INTENT(IN)              :: sphi_a
    1212             :       INTEGER, INTENT(IN)                                :: ldsa, ncob, nsgfb, sgfb
    1213             :       REAL(dp), DIMENSION(:, :), INTENT(IN)              :: sphi_b
    1214             :       INTEGER, INTENT(IN)                                :: ldsb
    1215             :       REAL(dp), DIMENSION(:, :), INTENT(IN)              :: cosab, sinab
    1216             :       INTEGER, INTENT(IN)                                :: ldab
    1217             :       REAL(dp), DIMENSION(:, :)                          :: work
    1218             :       INTEGER, INTENT(IN)                                :: ldwork
    1219             : 
    1220             : ! Calculate cosine
    1221             : 
    1222             :       CALL dgemm("N", "N", ncoa, nsgfb, ncob, 1.0_dp, cosab(1, 1), ldab, &
    1223       45486 :                  sphi_b(1, sgfb), ldsb, 0.0_dp, work(1, 1), ldwork)
    1224             : 
    1225             :       CALL dgemm("T", "N", nsgfa, nsgfb, ncoa, 1.0_dp, sphi_a(1, sgfa), ldsa, &
    1226       45486 :                  work(1, 1), ldwork, 1.0_dp, cos_block(sgfa, sgfb), SIZE(cos_block, 1))
    1227             : 
    1228             :       ! Calculate sine
    1229             :       CALL dgemm("N", "N", ncoa, nsgfb, ncob, 1.0_dp, sinab(1, 1), ldab, &
    1230       45486 :                  sphi_b(1, sgfb), ldsb, 0.0_dp, work(1, 1), ldwork)
    1231             : 
    1232             :       CALL dgemm("T", "N", nsgfa, nsgfb, ncoa, 1.0_dp, sphi_a(1, sgfa), ldsa, &
    1233       45486 :                  work(1, 1), ldwork, 1.0_dp, sin_block(sgfa, sgfb), SIZE(sin_block, 1))
    1234             : 
    1235       45486 :    END SUBROUTINE contract_all
    1236             : 
    1237             : END MODULE qs_efield_berry

Generated by: LCOV version 1.15