LCOV - code coverage report
Current view: top level - src - qs_efield_berry.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 94.8 % 649 615
Test Date: 2026-09-03 07:32:15 Functions: 100.0 % 5 5

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

Generated by: LCOV version 2.0-1