LCOV - code coverage report
Current view: top level - src - qs_efield_berry.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 94.7 % 642 608
Test Date: 2026-10-15 00:55:44 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: expikr
      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       136161 :    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       136161 :       CALL timeset(routineN, handle)
     118              : 
     119       136161 :       NULLIFY (dft_control)
     120              :       CALL get_qs_env(qs_env, s_mstruct_changed=s_mstruct_changed, &
     121       136161 :                       dft_control=dft_control)
     122              : 
     123       136161 :       IF (dft_control%apply_period_efield) THEN
     124              :          ! check if the periodic efield should be applied in the current step
     125         3818 :          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         3386 :             IF (s_mstruct_changed) CALL qs_efield_integrals(qs_env)
     129         3386 :             IF (dft_control%period_efield%displacement_field) THEN
     130          898 :                CALL qs_dispfield_derivatives(qs_env, just_energy, calculate_forces)
     131              :             ELSE
     132         2488 :                CALL qs_efield_derivatives(qs_env, just_energy, calculate_forces)
     133              :             END IF
     134              :          END IF
     135              :       END IF
     136              : 
     137       136161 :       CALL timestop(handle)
     138              : 
     139       136161 :    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         2488 :    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         9952 :       COMPLEX(dp), ALLOCATABLE                           :: dexpab(:, :, :, :), expab(:, :)
     195              :       INTEGER :: atom_a, atom_b, handle, i, ia, iatom, icenter, icol, idir, ikind, irow, iset, &
     196              :          ispin, j, jatom, jkind, jset, ldab, ldsa, ldsb, lsab, n1, n2, nao, natom, ncoa, ncob, &
     197              :          nkind, nmo, nseta, nsetb, sgfa, sgfb
     198         2488 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind
     199         2488 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
     200         2488 :                                                             npgfb, nsgfa, nsgfb
     201         2488 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
     202              :       LOGICAL                                            :: found, uniform, use_virial
     203              :       REAL(dp)                                           :: charge, ci(3), cqi(3), dab, dd, &
     204              :                                                             ener_field, f0, fab, fieldpol(3), &
     205              :                                                             focc, fpolvec(3), hmat(3, 3), occ, &
     206              :                                                             qi(3), strength, ti(3)
     207              :       REAL(dp), DIMENSION(3)                             :: forcea, forceb, kvec, ra, rab, rb, ria
     208         2488 :       REAL(dp), DIMENSION(:, :), POINTER                 :: iblock, rblock, work
     209         2488 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
     210         2488 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb
     211         2488 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     212        42296 :       TYPE(block_p_type), DIMENSION(3, 2)                :: dcost, dsint
     213              :       TYPE(cell_type), POINTER                           :: cell
     214         2488 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: eigrmat, inv_mat
     215              :       TYPE(cp_fm_struct_type), POINTER                   :: tmp_fm_struct
     216         2488 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: mo_coeff_tmp, mo_derivs_tmp
     217         2488 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: inv_work, op_fm_set, opvec
     218              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     219         2488 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, mo_derivs
     220         2488 :       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         2488 :       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         2488 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     227              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     228              :       TYPE(neighbor_list_iterator_p_type), &
     229         2488 :          DIMENSION(:), POINTER                           :: nl_iterator
     230              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     231         2488 :          POINTER                                         :: sab_orb
     232         2488 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     233              :       TYPE(qs_energy_type), POINTER                      :: energy
     234         2488 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
     235         2488 :       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         2488 :       CALL timeset(routineN, handle)
     240              : 
     241         2488 :       NULLIFY (dft_control, cell, particle_set)
     242              :       CALL get_qs_env(qs_env, dft_control=dft_control, cell=cell, &
     243         2488 :                       particle_set=particle_set, virial=virial)
     244         2488 :       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         2488 :                       efield=efield, energy=energy, para_env=para_env, sab_orb=sab_orb)
     247              : 
     248              :       ! calculate stress only if forces requested also
     249         2488 :       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         2488 :       strength = dft_control%period_efield%strength
     258         2488 :       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         9952 :       fieldpol = dft_control%period_efield%polarisation
     264        17416 :       fieldpol = fieldpol/NORM2(fieldpol)
     265         9952 :       fieldpol = -fieldpol*strength
     266        32344 :       hmat = cell%hmat(:, :)/twopi
     267         9952 :       DO idir = 1, 3
     268         9952 :          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         2488 :       natom = SIZE(particle_set)
     273         2488 :       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         9952 :       zi(:) = CMPLX(1._dp, 0._dp, dp)
     278         9344 :       DO ia = 1, natom
     279         6856 :          CALL get_atomic_kind(particle_set(ia)%atomic_kind, kind_number=ikind)
     280         6856 :          CALL get_qs_kind(qs_kind_set(ikind), core_charge=charge)
     281        27424 :          ria = particle_set(ia)%r
     282        27424 :          ria = pbc(ria, cell)
     283        27424 :          DO idir = 1, 3
     284        82272 :             kvec(:) = twopi*cell%h_inv(idir, :)
     285        82272 :             dd = SUM(kvec(:)*ria(:))
     286        20568 :             zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)**charge
     287        27424 :             zi(idir) = zi(idir)*zdeta
     288              :          END DO
     289         6856 :          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        16200 :          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         9952 :       qi = AIMAG(LOG(zi))
     303              : 
     304              :       ! check uniform occupation
     305         2488 :       NULLIFY (mos)
     306         2488 :       CALL get_qs_env(qs_env=qs_env, mos=mos)
     307         5078 :       DO ispin = 1, dft_control%nspins
     308         2590 :          CALL get_mo_set(mo_set=mos(ispin), maxocc=occ, uniform_occupation=uniform)
     309         5078 :          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         2488 :       NULLIFY (mo_derivs)
     315         2488 :       CALL get_qs_env(qs_env=qs_env, mo_derivs=mo_derivs)
     316              :       ! initialize all work matrices needed
     317        15234 :       ALLOCATE (op_fm_set(2, dft_control%nspins))
     318        15234 :       ALLOCATE (opvec(2, dft_control%nspins))
     319        10054 :       ALLOCATE (eigrmat(dft_control%nspins))
     320        10054 :       ALLOCATE (inv_mat(dft_control%nspins))
     321        15234 :       ALLOCATE (inv_work(2, dft_control%nspins))
     322        10054 :       ALLOCATE (mo_derivs_tmp(SIZE(mo_derivs)))
     323         7566 :       ALLOCATE (mo_coeff_tmp(SIZE(mo_derivs)))
     324              : 
     325              :       ! Allocate temp matrices for the wavefunction derivatives
     326         5078 :       DO ispin = 1, dft_control%nspins
     327         2590 :          NULLIFY (tmp_fm_struct, mo_coeff)
     328         2590 :          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         2590 :                                   ncol_global=nmo, para_env=para_env, context=mo_coeff%matrix_struct%context)
     331         2590 :          CALL cp_fm_create(mo_derivs_tmp(ispin), mo_coeff%matrix_struct)
     332         2590 :          CALL cp_fm_create(mo_coeff_tmp(ispin), mo_coeff%matrix_struct)
     333         2590 :          CALL copy_dbcsr_to_fm(mo_derivs(ispin)%matrix, mo_derivs_tmp(ispin))
     334         7770 :          DO i = 1, SIZE(op_fm_set, 1)
     335         5180 :             CALL cp_fm_create(opvec(i, ispin), mo_coeff%matrix_struct)
     336         5180 :             CALL cp_fm_create(op_fm_set(i, ispin), tmp_fm_struct)
     337         7770 :             CALL cp_fm_create(inv_work(i, ispin), op_fm_set(i, ispin)%matrix_struct)
     338              :          END DO
     339         2590 :          CALL cp_cfm_create(eigrmat(ispin), op_fm_set(1, ispin)%matrix_struct)
     340         2590 :          CALL cp_cfm_create(inv_mat(ispin), op_fm_set(1, ispin)%matrix_struct)
     341         7668 :          CALL cp_fm_struct_release(tmp_fm_struct)
     342              :       END DO
     343              :       ! temp matrices for force calculation
     344         2488 :       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         1036 :          ALLOCATE (expab(ldab, ldab), work(ldab, ldab))
     358          888 :          ALLOCATE (dexpab(ldab, ldab, 3, 2))
     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         9952 :       DO idir = 1, 3
     369         7464 :          ci(idir) = 0.0_dp
     370              :          zi(idir) = z_zero
     371         9952 :          IF (ABS(fpolvec(idir)) > 1.0E-12_dp) THEN
     372         3578 :             cosmat => efield%cosmat(idir)%matrix
     373         3578 :             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         7258 :             DO ispin = 1, dft_control%nspins ! spin
     377         3680 :                IF (mos(ispin)%use_mo_coeff_b) THEN
     378         3680 :                   CALL get_mo_set(mo_set=mos(ispin), nao=nao, mo_coeff_b=mo_coeff_b, nmo=nmo)
     379         3680 :                   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         3680 :                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         3680 :                                   op_fm_set(1, ispin))
     387         3680 :                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         7258 :                                   op_fm_set(2, ispin))
     390              :             END DO
     391              :             !second step invert C^T S_berry C
     392         3578 :             zdet = z_one
     393         7258 :             DO ispin = 1, dft_control%nspins
     394         3680 :                CALL cp_cfm_scale_and_add_fm(z_zero, eigrmat(ispin), z_one, op_fm_set(1, ispin))
     395         3680 :                CALL cp_cfm_scale_and_add_fm(z_one, eigrmat(ispin), -gaussi, op_fm_set(2, ispin))
     396         3680 :                CALL cp_cfm_set_all(inv_mat(ispin), z_zero, z_one)
     397         3680 :                CALL cp_cfm_solve(eigrmat(ispin), inv_mat(ispin), zdeta)
     398         7258 :                zdet = zdet*zdeta
     399              :             END DO
     400         3578 :             zi(idir) = zdet**occ
     401         3578 :             ci(idir) = AIMAG(LOG(zdet**occ))
     402              : 
     403         3578 :             IF (.NOT. just_energy) THEN
     404              :                !compute the orbital derivative
     405         3086 :                focc = fpolvec(idir)
     406         6232 :                DO ispin = 1, dft_control%nspins
     407        41570 :                   inv_work(1, ispin)%local_data(:, :) = REAL(inv_mat(ispin)%local_data(:, :), dp)
     408        41570 :                   inv_work(2, ispin)%local_data(:, :) = AIMAG(inv_mat(ispin)%local_data(:, :))
     409         3146 :                   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         3146 :                                      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         9378 :                                      1.0_dp, mo_derivs_tmp(ispin))
     414              :                END DO
     415              :             END IF
     416              : 
     417              :             !compute nuclear forces
     418         3578 :             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 both basis-center derivatives from one primitive recurrence.
     520              :                         CALL expikr(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, expab, dexpab(:, :, :, 1), dexpab(:, :, :, 2))
     523        45578 :                         DO icenter = 1, 2
     524       112454 :                            DO i = 1, 3
     525              :                               CALL contract_all(dcost(i, icenter)%block, dsint(i, icenter)%block, &
     526              :                                                 ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
     527              :                                                 ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
     528              :                                                 REAL(dexpab(1:ncoa, 1:ncob, i, icenter), KIND=dp), &
     529      9943144 :                                                 AIMAG(dexpab(1:ncoa, 1:ncob, i, icenter)), ncoa, work, ldab)
     530              :                            END DO
     531              :                         END DO
     532              :                      END DO
     533              :                   END DO
     534         6544 :                   forcea = 0.0_dp
     535         6544 :                   forceb = 0.0_dp
     536        13489 :                   DO ispin = 1, dft_control%nspins
     537         6945 :                      NULLIFY (rblock, iblock)
     538              :                      CALL dbcsr_get_block_p(matrix=tempmat(1, ispin)%matrix, &
     539         6945 :                                             row=irow, col=icol, BLOCK=rblock, found=found)
     540         6945 :                      CPASSERT(found)
     541              :                      CALL dbcsr_get_block_p(matrix=tempmat(2, ispin)%matrix, &
     542         6945 :                                             row=irow, col=icol, BLOCK=iblock, found=found)
     543         6945 :                      CPASSERT(found)
     544         6945 :                      n1 = SIZE(rblock, 1)
     545         6945 :                      n2 = SIZE(rblock, 2)
     546         6945 :                      CPASSERT(SIZE(iblock, 1) == n1)
     547         6945 :                      CPASSERT(SIZE(iblock, 2) == n2)
     548         6945 :                      CPASSERT(lsab >= n1)
     549         6945 :                      CPASSERT(lsab >= n2)
     550        27379 :                      IF (iatom <= jatom) THEN
     551        18948 :                         DO i = 1, 3
     552              :                            forcea(i) = forcea(i) + SUM(rblock(1:n1, 1:n2)*dsint(i, 1)%block(1:n1, 1:n2)) &
     553      1956675 :                                        - SUM(iblock(1:n1, 1:n2)*dcost(i, 1)%block(1:n1, 1:n2))
     554              :                            forceb(i) = forceb(i) + SUM(rblock(1:n1, 1:n2)*dsint(i, 2)%block(1:n1, 1:n2)) &
     555      1961412 :                                        - SUM(iblock(1:n1, 1:n2)*dcost(i, 2)%block(1:n1, 1:n2))
     556              :                         END DO
     557              :                      ELSE
     558         8832 :                         DO i = 1, 3
     559              :                            forcea(i) = forcea(i) + SUM(TRANSPOSE(rblock(1:n1, 1:n2))*dsint(i, 1)%block(1:n2, 1:n1)) &
     560       605304 :                                        - SUM(TRANSPOSE(iblock(1:n1, 1:n2))*dcost(i, 1)%block(1:n2, 1:n1))
     561              :                            forceb(i) = forceb(i) + SUM(TRANSPOSE(rblock(1:n1, 1:n2))*dsint(i, 2)%block(1:n2, 1:n1)) &
     562       607512 :                                        - SUM(TRANSPOSE(iblock(1:n1, 1:n2))*dcost(i, 2)%block(1:n2, 1:n1))
     563              :                         END DO
     564              :                      END IF
     565              :                   END DO
     566        26176 :                   force(ikind)%efield(1:3, atom_a) = force(ikind)%efield(1:3, atom_a) - fab*fpolvec(idir)*forcea(1:3)
     567        26176 :                   force(jkind)%efield(1:3, atom_b) = force(jkind)%efield(1:3, atom_b) - fab*fpolvec(idir)*forceb(1:3)
     568         6694 :                   IF (use_virial) THEN
     569            0 :                      f0 = -fab*fpolvec(idir)
     570            0 :                      CALL virial_pair_force(virial%pv_virial, f0, forcea, ra)
     571            0 :                      CALL virial_pair_force(virial%pv_virial, f0, forceb, rb)
     572              :                   END IF
     573              : 
     574              :                END DO
     575          150 :                CALL neighbor_list_iterator_release(nl_iterator)
     576          150 :                DEALLOCATE (basis_set_list)
     577              : 
     578              :             END IF
     579              :          END IF
     580              :       END DO
     581              : 
     582              :       ! Energy
     583         9952 :       ener_field = 0.0_dp
     584              :       ti = 0.0_dp
     585         9952 :       DO idir = 1, 3
     586              :          ! make sure the total normalized polarization is within [-1:1]
     587         7464 :          cqi(idir) = qi(idir) + ci(idir)
     588         7464 :          IF (cqi(idir) > pi) cqi(idir) = cqi(idir) - twopi
     589         7464 :          IF (cqi(idir) < -pi) cqi(idir) = cqi(idir) + twopi
     590              :          ! now check for log branch
     591         7464 :          IF (ABS(efield%polarisation(idir) - cqi(idir)) > pi) THEN
     592            0 :             ti(idir) = (efield%polarisation(idir) - cqi(idir))/pi
     593            0 :             DO i = 1, 10
     594            0 :                cqi(idir) = cqi(idir) + SIGN(1.0_dp, ti(idir))*twopi
     595            0 :                IF (ABS(efield%polarisation(idir) - cqi(idir)) < pi) EXIT
     596              :             END DO
     597              :          END IF
     598         9952 :          ener_field = ener_field + fpolvec(idir)*cqi(idir)
     599              :       END DO
     600              : 
     601              :       ! update the references
     602         2488 :       IF (calculate_forces) THEN
     603              :          ! check for smoothness of energy surface
     604          592 :          IF (ABS(efield%field_energy - ener_field) > pi*ABS(SUM(fpolvec))) THEN
     605           16 :             CPWARN("Large change of e-field energy detected. Correct for non-smooth energy surface")
     606              :          END IF
     607          148 :          efield%field_energy = ener_field
     608          592 :          efield%polarisation(:) = cqi(:)
     609              :       END IF
     610         2488 :       energy%efield = ener_field
     611              : 
     612         2488 :       IF (.NOT. just_energy) THEN
     613              :          ! Add the result to mo_derivativs
     614         3892 :          DO ispin = 1, dft_control%nspins
     615         3892 :             CALL copy_fm_to_dbcsr(mo_derivs_tmp(ispin), mo_derivs(ispin)%matrix)
     616              :          END DO
     617         1916 :          IF (use_virial) THEN
     618            0 :             ti = 0.0_dp
     619            0 :             DO i = 1, 3
     620            0 :                DO j = 1, 3
     621            0 :                   ti(j) = ti(j) + hmat(j, i)*cqi(i)
     622              :                END DO
     623              :             END DO
     624            0 :             DO i = 1, 3
     625            0 :                DO j = 1, 3
     626            0 :                   virial%pv_virial(i, j) = virial%pv_virial(i, j) - fieldpol(i)*ti(j)
     627              :                END DO
     628              :             END DO
     629              :          END IF
     630              :       END IF
     631              : 
     632         5078 :       DO ispin = 1, dft_control%nspins
     633         2590 :          CALL cp_cfm_release(eigrmat(ispin))
     634         2590 :          CALL cp_cfm_release(inv_mat(ispin))
     635         2590 :          CALL cp_fm_release(mo_derivs_tmp(ispin))
     636         2590 :          IF (mos(ispin)%use_mo_coeff_b) CALL cp_fm_release(mo_coeff_tmp(ispin))
     637        10258 :          DO i = 1, SIZE(op_fm_set, 1)
     638         5180 :             CALL cp_fm_release(opvec(i, ispin))
     639         5180 :             CALL cp_fm_release(op_fm_set(i, ispin))
     640         7770 :             CALL cp_fm_release(inv_work(i, ispin))
     641              :          END DO
     642              :       END DO
     643         2488 :       DEALLOCATE (inv_mat, inv_work, op_fm_set, opvec, eigrmat)
     644         2488 :       DEALLOCATE (mo_coeff_tmp, mo_derivs_tmp)
     645              : 
     646         2488 :       IF (calculate_forces) THEN
     647          444 :          DO ikind = 1, SIZE(atomic_kind_set)
     648         4204 :             CALL para_env%sum(force(ikind)%efield)
     649              :          END DO
     650          148 :          DEALLOCATE (expab, work, dexpab)
     651          592 :          DO i = 1, 3
     652          444 :             DEALLOCATE (dcost(i, 1)%block, dsint(i, 1)%block)
     653          592 :             DEALLOCATE (dcost(i, 2)%block, dsint(i, 2)%block)
     654              :          END DO
     655          148 :          CALL dbcsr_deallocate_matrix_set(tempmat)
     656              :       END IF
     657         2488 :       CALL timestop(handle)
     658              : 
     659         7464 :    END SUBROUTINE qs_efield_derivatives
     660              : 
     661              : ! **************************************************************************************************
     662              : !> \brief ...
     663              : !> \param qs_env ...
     664              : !> \param just_energy ...
     665              : !> \param calculate_forces ...
     666              : ! **************************************************************************************************
     667          898 :    SUBROUTINE qs_dispfield_derivatives(qs_env, just_energy, calculate_forces)
     668              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     669              :       LOGICAL, INTENT(IN)                                :: just_energy, calculate_forces
     670              : 
     671              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_dispfield_derivatives'
     672              : 
     673              :       COMPLEX(dp)                                        :: zdet, zdeta, zi(3)
     674         3592 :       COMPLEX(dp), ALLOCATABLE                           :: dexpab(:, :, :, :), expab(:, :)
     675              :       INTEGER :: handle, i, ia, iatom, icenter, icol, idir, ikind, iodeb, irow, iset, ispin, &
     676              :          jatom, jkind, jset, ldab, ldsa, ldsb, lsab, n1, n2, nao, natom, ncoa, ncob, nkind, nmo, &
     677              :          nseta, nsetb, sgfa, sgfb
     678          898 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind
     679          898 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
     680          898 :                                                             npgfb, nsgfa, nsgfb
     681          898 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
     682              :       LOGICAL                                            :: found, uniform, use_virial
     683              :       REAL(dp) :: charge, ci(3), cqi(3), dab, dd, di(3), ener_field, fab, fieldpol(3), focc, &
     684              :          hmat(3, 3), occ, omega, qi(3), rlog(3), strength, zlog(3)
     685              :       REAL(dp), DIMENSION(3)                             :: dfilter, forcea, forceb, kvec, ra, rab, &
     686              :                                                             rb, ria
     687          898 :       REAL(dp), DIMENSION(:, :), POINTER                 :: iblock, rblock, work
     688          898 :       REAL(dp), DIMENSION(:, :, :), POINTER              :: force_tmp
     689          898 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
     690          898 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb
     691          898 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     692        15266 :       TYPE(block_p_type), DIMENSION(3, 2)                :: dcost, dsint
     693              :       TYPE(cell_type), POINTER                           :: cell
     694          898 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: eigrmat, inv_mat
     695              :       TYPE(cp_fm_struct_type), POINTER                   :: tmp_fm_struct
     696          898 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: mo_coeff_tmp
     697          898 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: inv_work, mo_derivs_tmp, op_fm_set, opvec
     698              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     699          898 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, mo_derivs
     700          898 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: tempmat
     701              :       TYPE(dbcsr_type), POINTER                          :: cosmat, mo_coeff_b, sinmat
     702              :       TYPE(dft_control_type), POINTER                    :: dft_control
     703              :       TYPE(efield_berry_type), POINTER                   :: efield
     704          898 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     705              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     706          898 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     707              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     708              :       TYPE(neighbor_list_iterator_p_type), &
     709          898 :          DIMENSION(:), POINTER                           :: nl_iterator
     710              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     711          898 :          POINTER                                         :: sab_orb
     712          898 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     713              :       TYPE(qs_energy_type), POINTER                      :: energy
     714          898 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
     715          898 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     716              :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     717              :       TYPE(virial_type), POINTER                         :: virial
     718              : 
     719          898 :       CALL timeset(routineN, handle)
     720              : 
     721          898 :       NULLIFY (dft_control, cell, particle_set)
     722              :       CALL get_qs_env(qs_env, dft_control=dft_control, cell=cell, &
     723          898 :                       particle_set=particle_set, virial=virial)
     724          898 :       NULLIFY (qs_kind_set, efield, para_env, sab_orb)
     725              :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
     726          898 :                       efield=efield, energy=energy, para_env=para_env, sab_orb=sab_orb)
     727              : 
     728              :       ! calculate stress only if forces requested also
     729          898 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
     730            0 :       use_virial = use_virial .AND. calculate_forces
     731              :       ! disable stress calculation
     732              :       IF (use_virial) THEN
     733            0 :          CPABORT("Stress tensor for periodic D-field not implemented")
     734              :       END IF
     735              : 
     736         3592 :       dfilter(1:3) = dft_control%period_efield%d_filter(1:3)
     737              : 
     738              :       ! if an intensities list is given, select the value for the current step
     739          898 :       strength = dft_control%period_efield%strength
     740          898 :       IF (ALLOCATED(dft_control%period_efield%strength_list)) THEN
     741              :          strength = dft_control%period_efield%strength_list(MOD(qs_env%sim_step &
     742            0 :                                         - dft_control%period_efield%start_frame, SIZE(dft_control%period_efield%strength_list)) + 1)
     743              :       END IF
     744              : 
     745         3592 :       fieldpol = dft_control%period_efield%polarisation
     746         6286 :       fieldpol = fieldpol/NORM2(fieldpol)
     747         3592 :       fieldpol = fieldpol*strength
     748              : 
     749          898 :       omega = cell%deth
     750        11674 :       hmat = cell%hmat(:, :)/(twopi*omega)
     751              : 
     752              :       ! nuclear contribution to polarization
     753          898 :       natom = SIZE(particle_set)
     754          898 :       IF (calculate_forces) THEN
     755           10 :          CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, force=force)
     756           10 :          CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind)
     757           40 :          ALLOCATE (force_tmp(natom, 3, 3))
     758          310 :          force_tmp = 0.0_dp
     759              :       END IF
     760         3592 :       zi(:) = CMPLX(1._dp, 0._dp, dp)
     761         2694 :       DO ia = 1, natom
     762         1796 :          CALL get_atomic_kind(particle_set(ia)%atomic_kind, kind_number=ikind)
     763         1796 :          CALL get_qs_kind(qs_kind_set(ikind), core_charge=charge)
     764         7184 :          ria = particle_set(ia)%r
     765         7184 :          ria = pbc(ria, cell)
     766         7184 :          DO idir = 1, 3
     767        21552 :             kvec(:) = twopi*cell%h_inv(idir, :)
     768        21552 :             dd = SUM(kvec(:)*ria(:))
     769         5388 :             zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)**charge
     770         7184 :             zi(idir) = zi(idir)*zdeta
     771              :          END DO
     772         4490 :          IF (calculate_forces) THEN
     773           20 :             IF (para_env%mepos == 0) THEN
     774           40 :                DO i = 1, 3
     775           40 :                   force_tmp(ia, i, i) = force_tmp(ia, i, i) + charge/omega
     776              :                END DO
     777              :             END IF
     778              :          END IF
     779              :       END DO
     780         3592 :       rlog = AIMAG(LOG(zi))
     781              : 
     782              :       ! check uniform occupation
     783          898 :       NULLIFY (mos)
     784          898 :       CALL get_qs_env(qs_env=qs_env, mos=mos)
     785         1796 :       DO ispin = 1, dft_control%nspins
     786          898 :          CALL get_mo_set(mo_set=mos(ispin), maxocc=occ, uniform_occupation=uniform)
     787         1796 :          IF (.NOT. uniform) THEN
     788            0 :             CPABORT("Berry phase moments for non uniform MO occupation numbers not implemented")
     789              :          END IF
     790              :       END DO
     791              : 
     792              :       ! initialize all work matrices needed
     793          898 :       NULLIFY (mo_derivs)
     794          898 :       CALL get_qs_env(qs_env=qs_env, mo_derivs=mo_derivs)
     795         5388 :       ALLOCATE (op_fm_set(2, dft_control%nspins))
     796         5388 :       ALLOCATE (opvec(2, dft_control%nspins))
     797         3592 :       ALLOCATE (eigrmat(dft_control%nspins))
     798         3592 :       ALLOCATE (inv_mat(dft_control%nspins))
     799         5388 :       ALLOCATE (inv_work(2, dft_control%nspins))
     800         6286 :       ALLOCATE (mo_derivs_tmp(3, SIZE(mo_derivs)))
     801         3592 :       ALLOCATE (mo_coeff_tmp(SIZE(mo_derivs)))
     802              : 
     803              :       ! Allocate temp matrices for the wavefunction derivatives
     804         1796 :       DO ispin = 1, dft_control%nspins
     805          898 :          NULLIFY (tmp_fm_struct, mo_coeff)
     806          898 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nao=nao, nmo=nmo)
     807              :          CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=nmo, &
     808          898 :                                   ncol_global=nmo, para_env=para_env, context=mo_coeff%matrix_struct%context)
     809          898 :          CALL cp_fm_create(mo_coeff_tmp(ispin), mo_coeff%matrix_struct)
     810         3592 :          DO i = 1, 3
     811         2694 :             CALL cp_fm_create(mo_derivs_tmp(i, ispin), mo_coeff%matrix_struct)
     812         3592 :             CALL cp_fm_set_all(matrix=mo_derivs_tmp(i, ispin), alpha=0.0_dp)
     813              :          END DO
     814         2694 :          DO i = 1, SIZE(op_fm_set, 1)
     815         1796 :             CALL cp_fm_create(opvec(i, ispin), mo_coeff%matrix_struct)
     816         1796 :             CALL cp_fm_create(op_fm_set(i, ispin), tmp_fm_struct)
     817         2694 :             CALL cp_fm_create(inv_work(i, ispin), op_fm_set(i, ispin)%matrix_struct)
     818              :          END DO
     819          898 :          CALL cp_cfm_create(eigrmat(ispin), op_fm_set(1, ispin)%matrix_struct)
     820          898 :          CALL cp_cfm_create(inv_mat(ispin), op_fm_set(1, ispin)%matrix_struct)
     821         2694 :          CALL cp_fm_struct_release(tmp_fm_struct)
     822              :       END DO
     823              :       ! temp matrices for force calculation
     824          898 :       IF (calculate_forces) THEN
     825           10 :          NULLIFY (matrix_s)
     826           10 :          CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s)
     827           60 :          ALLOCATE (tempmat(2, dft_control%nspins))
     828           20 :          DO ispin = 1, dft_control%nspins
     829           10 :             ALLOCATE (tempmat(1, ispin)%matrix, tempmat(2, ispin)%matrix)
     830           10 :             CALL dbcsr_copy(tempmat(1, ispin)%matrix, matrix_s(1)%matrix, 'TEMPMAT')
     831           10 :             CALL dbcsr_copy(tempmat(2, ispin)%matrix, matrix_s(1)%matrix, 'TEMPMAT')
     832           10 :             CALL dbcsr_set(tempmat(1, ispin)%matrix, 0.0_dp)
     833           20 :             CALL dbcsr_set(tempmat(2, ispin)%matrix, 0.0_dp)
     834              :          END DO
     835              :          ! integration
     836           10 :          CALL get_qs_kind_set(qs_kind_set, maxco=ldab, maxsgf=lsab)
     837           70 :          ALLOCATE (expab(ldab, ldab), work(ldab, ldab))
     838           60 :          ALLOCATE (dexpab(ldab, ldab, 3, 2))
     839           10 :          lsab = MAX(lsab, ldab)
     840           50 :          DO i = 1, 3
     841          180 :             ALLOCATE (dcost(i, 1)%block(lsab, lsab), dsint(i, 1)%block(lsab, lsab))
     842          160 :             ALLOCATE (dcost(i, 2)%block(lsab, lsab), dsint(i, 2)%block(lsab, lsab))
     843              :          END DO
     844              :       END IF
     845              : 
     846              :       !Start the MO derivative calculation
     847              :       !loop over all cell vectors
     848         3592 :       DO idir = 1, 3
     849         2694 :          zi(idir) = z_zero
     850         2694 :          cosmat => efield%cosmat(idir)%matrix
     851         2694 :          sinmat => efield%sinmat(idir)%matrix
     852              :          !evaluate the expression needed for the derivative (S_berry * C  and [C^T S_berry C]^-1)
     853              :          !first step S_berry * C  and C^T S_berry C
     854         5388 :          DO ispin = 1, dft_control%nspins ! spin
     855         2694 :             IF (mos(ispin)%use_mo_coeff_b) THEN
     856         2694 :                CALL get_mo_set(mo_set=mos(ispin), nao=nao, mo_coeff_b=mo_coeff_b, nmo=nmo)
     857         2694 :                CALL copy_dbcsr_to_fm(mo_coeff_b, mo_coeff_tmp(ispin))
     858              :             ELSE
     859            0 :                CALL get_mo_set(mo_set=mos(ispin), nao=nao, mo_coeff=mo_coeff, nmo=nmo)
     860            0 :                mo_coeff_tmp(ispin) = mo_coeff
     861              :             END IF
     862         2694 :             CALL cp_dbcsr_sm_fm_multiply(cosmat, mo_coeff_tmp(ispin), opvec(1, ispin), ncol=nmo)
     863              :             CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff_tmp(ispin), opvec(1, ispin), 0.0_dp, &
     864         2694 :                                op_fm_set(1, ispin))
     865         2694 :             CALL cp_dbcsr_sm_fm_multiply(sinmat, mo_coeff_tmp(ispin), opvec(2, ispin), ncol=nmo)
     866              :             CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff_tmp(ispin), opvec(2, ispin), 0.0_dp, &
     867         5388 :                                op_fm_set(2, ispin))
     868              :          END DO
     869              :          !second step invert C^T S_berry C
     870         2694 :          zdet = z_one
     871         5388 :          DO ispin = 1, dft_control%nspins
     872         2694 :             CALL cp_cfm_scale_and_add_fm(z_zero, eigrmat(ispin), z_one, op_fm_set(1, ispin))
     873         2694 :             CALL cp_cfm_scale_and_add_fm(z_one, eigrmat(ispin), -gaussi, op_fm_set(2, ispin))
     874         2694 :             CALL cp_cfm_set_all(inv_mat(ispin), z_zero, z_one)
     875         2694 :             CALL cp_cfm_solve(eigrmat(ispin), inv_mat(ispin), zdeta)
     876         5388 :             zdet = zdet*zdeta
     877              :          END DO
     878         2694 :          zi(idir) = zdet**occ
     879         2694 :          zlog(idir) = AIMAG(LOG(zi(idir)))
     880              : 
     881         2694 :          IF (.NOT. just_energy) THEN
     882              :             !compute the orbital derivative
     883         5388 :             DO ispin = 1, dft_control%nspins
     884        35022 :                inv_work(1, ispin)%local_data(:, :) = REAL(inv_mat(ispin)%local_data(:, :), dp)
     885        35022 :                inv_work(2, ispin)%local_data(:, :) = AIMAG(inv_mat(ispin)%local_data(:, :))
     886         2694 :                CALL get_mo_set(mo_set=mos(ispin), nao=nao, nmo=nmo)
     887        13470 :                DO i = 1, 3
     888         8082 :                   focc = hmat(idir, i)
     889              :                   CALL parallel_gemm("N", "N", nao, nmo, nmo, focc, opvec(1, ispin), inv_work(2, ispin), &
     890         8082 :                                      1.0_dp, mo_derivs_tmp(idir, ispin))
     891              :                   CALL parallel_gemm("N", "N", nao, nmo, nmo, -focc, opvec(2, ispin), inv_work(1, ispin), &
     892        10776 :                                      1.0_dp, mo_derivs_tmp(idir, ispin))
     893              :                END DO
     894              :             END DO
     895              :          END IF
     896              : 
     897              :          !compute nuclear forces
     898         3592 :          IF (calculate_forces) THEN
     899           30 :             nkind = SIZE(qs_kind_set)
     900           30 :             natom = SIZE(particle_set)
     901          120 :             kvec(:) = twopi*cell%h_inv(idir, :)
     902              : 
     903              :             ! calculate: C [C^T S_berry C]^(-1) C^T
     904              :             ! Store this matrix in DBCSR form (only S overlap blocks)
     905           60 :             DO ispin = 1, dft_control%nspins
     906           30 :                CALL dbcsr_set(tempmat(1, ispin)%matrix, 0.0_dp)
     907           30 :                CALL dbcsr_set(tempmat(2, ispin)%matrix, 0.0_dp)
     908           30 :                CALL get_mo_set(mo_set=mos(ispin), nao=nao, nmo=nmo)
     909              :                CALL parallel_gemm("N", "N", nao, nmo, nmo, 1.0_dp, mo_coeff_tmp(ispin), inv_work(1, ispin), 0.0_dp, &
     910           30 :                                   opvec(1, ispin))
     911              :                CALL parallel_gemm("N", "N", nao, nmo, nmo, 1.0_dp, mo_coeff_tmp(ispin), inv_work(2, ispin), 0.0_dp, &
     912           30 :                                   opvec(2, ispin))
     913              :                CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=tempmat(1, ispin)%matrix, &
     914           30 :                                           matrix_v=opvec(1, ispin), matrix_g=mo_coeff_tmp(ispin), ncol=nmo)
     915              :                CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=tempmat(2, ispin)%matrix, &
     916           90 :                                           matrix_v=opvec(2, ispin), matrix_g=mo_coeff_tmp(ispin), ncol=nmo)
     917              :             END DO
     918              : 
     919              :             ! Calculation of derivative integrals (da|eikr|b) and (a|eikr|db)
     920          150 :             ALLOCATE (basis_set_list(nkind))
     921           90 :             DO ikind = 1, nkind
     922           60 :                qs_kind => qs_kind_set(ikind)
     923           60 :                CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
     924           90 :                IF (ASSOCIATED(basis_set_a)) THEN
     925           60 :                   basis_set_list(ikind)%gto_basis_set => basis_set_a
     926              :                ELSE
     927            0 :                   NULLIFY (basis_set_list(ikind)%gto_basis_set)
     928              :                END IF
     929              :             END DO
     930              :             !
     931           30 :             CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
     932          585 :             DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     933              :                CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, &
     934          555 :                                       iatom=iatom, jatom=jatom, r=rab)
     935          555 :                basis_set_a => basis_set_list(ikind)%gto_basis_set
     936          555 :                IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     937          555 :                basis_set_b => basis_set_list(jkind)%gto_basis_set
     938          555 :                IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     939              :                ! basis ikind
     940          555 :                first_sgfa => basis_set_a%first_sgf
     941          555 :                la_max => basis_set_a%lmax
     942          555 :                la_min => basis_set_a%lmin
     943          555 :                npgfa => basis_set_a%npgf
     944          555 :                nseta = basis_set_a%nset
     945          555 :                nsgfa => basis_set_a%nsgf_set
     946          555 :                rpgfa => basis_set_a%pgf_radius
     947          555 :                set_radius_a => basis_set_a%set_radius
     948          555 :                sphi_a => basis_set_a%sphi
     949          555 :                zeta => basis_set_a%zet
     950              :                ! basis jkind
     951          555 :                first_sgfb => basis_set_b%first_sgf
     952          555 :                lb_max => basis_set_b%lmax
     953          555 :                lb_min => basis_set_b%lmin
     954          555 :                npgfb => basis_set_b%npgf
     955          555 :                nsetb = basis_set_b%nset
     956          555 :                nsgfb => basis_set_b%nsgf_set
     957          555 :                rpgfb => basis_set_b%pgf_radius
     958          555 :                set_radius_b => basis_set_b%set_radius
     959          555 :                sphi_b => basis_set_b%sphi
     960          555 :                zetb => basis_set_b%zet
     961              : 
     962          555 :                ldsa = SIZE(sphi_a, 1)
     963          555 :                ldsb = SIZE(sphi_b, 1)
     964          555 :                ra(:) = pbc(particle_set(iatom)%r(:), cell)
     965         2220 :                rb(:) = ra + rab
     966          555 :                dab = SQRT(rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3))
     967              : 
     968          555 :                IF (iatom <= jatom) THEN
     969          354 :                   irow = iatom
     970          354 :                   icol = jatom
     971              :                ELSE
     972          201 :                   irow = jatom
     973          201 :                   icol = iatom
     974              :                END IF
     975              : 
     976          555 :                IF (iatom == jatom) THEN
     977              :                   fab = 1.0_dp*occ
     978              :                ELSE
     979          201 :                   fab = 2.0_dp*occ
     980              :                END IF
     981              : 
     982         2220 :                DO i = 1, 3
     983       454545 :                   dcost(i, 1)%block = 0.0_dp
     984       454545 :                   dsint(i, 1)%block = 0.0_dp
     985       454545 :                   dcost(i, 2)%block = 0.0_dp
     986       455100 :                   dsint(i, 2)%block = 0.0_dp
     987              :                END DO
     988              : 
     989         1665 :                DO iset = 1, nseta
     990         1110 :                   ncoa = npgfa(iset)*ncoset(la_max(iset))
     991         1110 :                   sgfa = first_sgfa(1, iset)
     992         3885 :                   DO jset = 1, nsetb
     993         2220 :                      IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
     994         1140 :                      ncob = npgfb(jset)*ncoset(lb_max(jset))
     995         1140 :                      sgfb = first_sgfb(1, jset)
     996              :                      ! Calculate both basis-center derivatives from one primitive recurrence.
     997              :                      CALL expikr(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
     998              :                                  lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), lb_min(jset), &
     999         1140 :                                  ra, rb, kvec, expab, dexpab(:, :, :, 1), dexpab(:, :, :, 2))
    1000         4530 :                      DO icenter = 1, 2
    1001        11340 :                         DO i = 1, 3
    1002              :                            CALL contract_all(dcost(i, icenter)%block, dsint(i, icenter)%block, &
    1003              :                                              ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
    1004              :                                              ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
    1005              :                                              REAL(dexpab(1:ncoa, 1:ncob, i, icenter), KIND=dp), &
    1006      1123392 :                                              AIMAG(dexpab(1:ncoa, 1:ncob, i, icenter)), ncoa, work, ldab)
    1007              :                         END DO
    1008              :                      END DO
    1009              :                   END DO
    1010              :                END DO
    1011          555 :                forcea = 0.0_dp
    1012          555 :                forceb = 0.0_dp
    1013         1110 :                DO ispin = 1, dft_control%nspins
    1014          555 :                   NULLIFY (rblock, iblock)
    1015              :                   CALL dbcsr_get_block_p(matrix=tempmat(1, ispin)%matrix, &
    1016          555 :                                          row=irow, col=icol, BLOCK=rblock, found=found)
    1017          555 :                   CPASSERT(found)
    1018              :                   CALL dbcsr_get_block_p(matrix=tempmat(2, ispin)%matrix, &
    1019          555 :                                          row=irow, col=icol, BLOCK=iblock, found=found)
    1020          555 :                   CPASSERT(found)
    1021          555 :                   n1 = SIZE(rblock, 1)
    1022          555 :                   n2 = SIZE(rblock, 2)
    1023          555 :                   CPASSERT(SIZE(iblock, 1) == n1)
    1024          555 :                   CPASSERT(SIZE(iblock, 2) == n2)
    1025          555 :                   CPASSERT(lsab >= n1)
    1026          555 :                   CPASSERT(lsab >= n2)
    1027         2220 :                   IF (iatom <= jatom) THEN
    1028         1416 :                      DO i = 1, 3
    1029              :                         forcea(i) = forcea(i) + SUM(rblock(1:n1, 1:n2)*dsint(i, 1)%block(1:n1, 1:n2)) &
    1030       160542 :                                     - SUM(iblock(1:n1, 1:n2)*dcost(i, 1)%block(1:n1, 1:n2))
    1031              :                         forceb(i) = forceb(i) + SUM(rblock(1:n1, 1:n2)*dsint(i, 2)%block(1:n1, 1:n2)) &
    1032       160896 :                                     - SUM(iblock(1:n1, 1:n2)*dcost(i, 2)%block(1:n1, 1:n2))
    1033              :                      END DO
    1034              :                   ELSE
    1035          804 :                      DO i = 1, 3
    1036              :                         forcea(i) = forcea(i) + SUM(TRANSPOSE(rblock(1:n1, 1:n2))*dsint(i, 1)%block(1:n2, 1:n1)) &
    1037        85023 :                                     - SUM(TRANSPOSE(iblock(1:n1, 1:n2))*dcost(i, 1)%block(1:n2, 1:n1))
    1038              :                         forceb(i) = forceb(i) + SUM(TRANSPOSE(rblock(1:n1, 1:n2))*dsint(i, 2)%block(1:n2, 1:n1)) &
    1039        85224 :                                     - SUM(TRANSPOSE(iblock(1:n1, 1:n2))*dcost(i, 2)%block(1:n2, 1:n1))
    1040              :                      END DO
    1041              :                   END IF
    1042              :                END DO
    1043         2250 :                DO i = 1, 3
    1044         6660 :                   force_tmp(iatom, :, i) = force_tmp(iatom, :, i) - fab*hmat(i, idir)*forcea(:)
    1045         7215 :                   force_tmp(jatom, :, i) = force_tmp(jatom, :, i) - fab*hmat(i, idir)*forceb(:)
    1046              :                END DO
    1047              :             END DO
    1048           30 :             CALL neighbor_list_iterator_release(nl_iterator)
    1049           30 :             DEALLOCATE (basis_set_list)
    1050              :          END IF
    1051              :       END DO
    1052              : 
    1053              :       ! make sure the total normalized polarization is within [-1:1]
    1054         3592 :       DO idir = 1, 3
    1055         2694 :          cqi(idir) = rlog(idir) + zlog(idir)
    1056         2694 :          IF (cqi(idir) > pi) cqi(idir) = cqi(idir) - twopi
    1057         2694 :          IF (cqi(idir) < -pi) cqi(idir) = cqi(idir) + twopi
    1058              :          ! now check for log branch
    1059         3592 :          IF (calculate_forces) THEN
    1060           30 :             IF (ABS(efield%polarisation(idir) - cqi(idir)) > pi) THEN
    1061            0 :                di(idir) = (efield%polarisation(idir) - cqi(idir))/pi
    1062            0 :                DO i = 1, 10
    1063            0 :                   cqi(idir) = cqi(idir) + SIGN(1.0_dp, di(idir))*twopi
    1064            0 :                   IF (ABS(efield%polarisation(idir) - cqi(idir)) < pi) EXIT
    1065              :                END DO
    1066              :             END IF
    1067              :          END IF
    1068              :       END DO
    1069         3592 :       DO idir = 1, 3
    1070         2694 :          qi(idir) = 0.0_dp
    1071         2694 :          ci(idir) = 0.0_dp
    1072        11674 :          DO i = 1, 3
    1073        10776 :             ci(idir) = ci(idir) + hmat(idir, i)*cqi(i)
    1074              :          END DO
    1075              :       END DO
    1076              : 
    1077              :       ! update the references
    1078          898 :       IF (calculate_forces) THEN
    1079           40 :          ener_field = SUM(ci)
    1080              :          ! check for smoothness of energy surface
    1081          130 :          IF (ABS(efield%field_energy - ener_field) > pi*ABS(SUM(hmat))) THEN
    1082            0 :             CPWARN("Large change of e-field energy detected. Correct for non-smooth energy surface")
    1083              :          END IF
    1084           10 :          efield%field_energy = ener_field
    1085           40 :          efield%polarisation(:) = cqi(:)
    1086              :       END IF
    1087              : 
    1088              :       ! Energy
    1089          898 :       ener_field = 0.0_dp
    1090         3592 :       DO i = 1, 3
    1091         3592 :          ener_field = ener_field + dfilter(i)*(fieldpol(i) - 2._dp*twopi*ci(i))**2
    1092              :       END DO
    1093          898 :       energy%efield = 0.25_dp*omega/twopi*ener_field
    1094              : 
    1095              :       ! debugging output
    1096              :       IF (para_env%is_source()) THEN
    1097          898 :          iodeb = -1
    1098              :          IF (iodeb > 0) THEN
    1099              :             WRITE (iodeb, '(A,T61,F20.10)') "  Polarisation Quantum:  ", 2._dp*twopi*twopi*hmat(3, 3)
    1100              :             WRITE (iodeb, '(A,T21,3F20.10)') "  Polarisation: ", 2._dp*twopi*ci(1:3)
    1101              :             WRITE (iodeb, '(A,T21,3F20.10)') "  Displacement: ", fieldpol(1:3)
    1102              :             WRITE (iodeb, '(A,T21,3F20.10)') "  E-Field:      ", ((fieldpol(i) - 2._dp*twopi*ci(i)), i=1, 3)
    1103              :             WRITE (iodeb, '(A,T61,F20.10)') "  Disp Free Energy:", energy%efield
    1104              :          END IF
    1105              :       END IF
    1106              : 
    1107          898 :       IF (.NOT. just_energy) THEN
    1108         3592 :          DO i = 1, 3
    1109         3592 :             di(i) = -omega*(fieldpol(i) - 2._dp*twopi*ci(i))*dfilter(i)
    1110              :          END DO
    1111              :          ! Add the result to mo_derivativs
    1112         1796 :          DO ispin = 1, dft_control%nspins
    1113          898 :             CALL copy_dbcsr_to_fm(mo_derivs(ispin)%matrix, mo_coeff_tmp(ispin))
    1114         4490 :             DO idir = 1, 3
    1115              :                CALL cp_fm_scale_and_add(1.0_dp, mo_coeff_tmp(ispin), di(idir), &
    1116         3592 :                                         mo_derivs_tmp(idir, ispin))
    1117              :             END DO
    1118              :          END DO
    1119         1796 :          DO ispin = 1, dft_control%nspins
    1120         1796 :             CALL copy_fm_to_dbcsr(mo_coeff_tmp(ispin), mo_derivs(ispin)%matrix)
    1121              :          END DO
    1122              :       END IF
    1123              : 
    1124          898 :       IF (calculate_forces) THEN
    1125           40 :          DO i = 1, 3
    1126          100 :             DO ia = 1, natom
    1127           60 :                CALL get_atomic_kind(particle_set(ia)%atomic_kind, kind_number=ikind)
    1128           60 :                iatom = atom_of_kind(ia)
    1129          450 :                force(ikind)%efield(1:3, iatom) = force(ikind)%efield(1:3, iatom) + di(i)*force_tmp(ia, 1:3, i)
    1130              :             END DO
    1131              :          END DO
    1132              :       END IF
    1133              : 
    1134         1796 :       DO ispin = 1, dft_control%nspins
    1135          898 :          CALL cp_cfm_release(eigrmat(ispin))
    1136          898 :          CALL cp_cfm_release(inv_mat(ispin))
    1137          898 :          IF (mos(ispin)%use_mo_coeff_b) CALL cp_fm_release(mo_coeff_tmp(ispin))
    1138         3592 :          DO i = 1, 3
    1139         3592 :             CALL cp_fm_release(mo_derivs_tmp(i, ispin))
    1140              :          END DO
    1141         3592 :          DO i = 1, SIZE(op_fm_set, 1)
    1142         1796 :             CALL cp_fm_release(opvec(i, ispin))
    1143         1796 :             CALL cp_fm_release(op_fm_set(i, ispin))
    1144         2694 :             CALL cp_fm_release(inv_work(i, ispin))
    1145              :          END DO
    1146              :       END DO
    1147          898 :       DEALLOCATE (inv_mat, inv_work, op_fm_set, opvec, eigrmat)
    1148          898 :       DEALLOCATE (mo_coeff_tmp, mo_derivs_tmp)
    1149              : 
    1150          898 :       IF (calculate_forces) THEN
    1151           30 :          DO ikind = 1, SIZE(atomic_kind_set)
    1152          190 :             CALL para_env%sum(force(ikind)%efield)
    1153              :          END DO
    1154           10 :          DEALLOCATE (force_tmp)
    1155           10 :          DEALLOCATE (expab, work, dexpab)
    1156           40 :          DO i = 1, 3
    1157           30 :             DEALLOCATE (dcost(i, 1)%block, dsint(i, 1)%block)
    1158           40 :             DEALLOCATE (dcost(i, 2)%block, dsint(i, 2)%block)
    1159              :          END DO
    1160           10 :          CALL dbcsr_deallocate_matrix_set(tempmat)
    1161              :       END IF
    1162          898 :       CALL timestop(handle)
    1163              : 
    1164         2694 :    END SUBROUTINE qs_dispfield_derivatives
    1165              : 
    1166              : ! **************************************************************************************************
    1167              : !> \brief ...
    1168              : !> \param cos_block ...
    1169              : !> \param sin_block ...
    1170              : !> \param ncoa ...
    1171              : !> \param nsgfa ...
    1172              : !> \param sgfa ...
    1173              : !> \param sphi_a ...
    1174              : !> \param ldsa ...
    1175              : !> \param ncob ...
    1176              : !> \param nsgfb ...
    1177              : !> \param sgfb ...
    1178              : !> \param sphi_b ...
    1179              : !> \param ldsb ...
    1180              : !> \param cosab ...
    1181              : !> \param sinab ...
    1182              : !> \param ldab ...
    1183              : !> \param work ...
    1184              : !> \param ldwork ...
    1185              : ! **************************************************************************************************
    1186        73992 :    SUBROUTINE contract_all(cos_block, sin_block, &
    1187       147984 :                            ncoa, nsgfa, sgfa, sphi_a, ldsa, &
    1188       147984 :                            ncob, nsgfb, sgfb, sphi_b, ldsb, &
    1189        73992 :                            cosab, sinab, ldab, work, ldwork)
    1190              : 
    1191              :       REAL(dp), DIMENSION(:, :), POINTER                 :: cos_block, sin_block
    1192              :       INTEGER, INTENT(IN)                                :: ncoa, nsgfa, sgfa
    1193              :       REAL(dp), DIMENSION(:, :), INTENT(IN)              :: sphi_a
    1194              :       INTEGER, INTENT(IN)                                :: ldsa, ncob, nsgfb, sgfb
    1195              :       REAL(dp), DIMENSION(:, :), INTENT(IN)              :: sphi_b
    1196              :       INTEGER, INTENT(IN)                                :: ldsb
    1197              :       REAL(dp), DIMENSION(:, :), INTENT(IN)              :: cosab, sinab
    1198              :       INTEGER, INTENT(IN)                                :: ldab
    1199              :       REAL(dp), DIMENSION(:, :)                          :: work
    1200              :       INTEGER, INTENT(IN)                                :: ldwork
    1201              : 
    1202              : ! Calculate cosine
    1203              : 
    1204              :       CALL dgemm("N", "N", ncoa, nsgfb, ncob, 1.0_dp, cosab(1, 1), ldab, &
    1205        73992 :                  sphi_b(1, sgfb), ldsb, 0.0_dp, work(1, 1), ldwork)
    1206              : 
    1207              :       CALL dgemm("T", "N", nsgfa, nsgfb, ncoa, 1.0_dp, sphi_a(1, sgfa), ldsa, &
    1208        73992 :                  work(1, 1), ldwork, 1.0_dp, cos_block(sgfa, sgfb), SIZE(cos_block, 1))
    1209              : 
    1210              :       ! Calculate sine
    1211              :       CALL dgemm("N", "N", ncoa, nsgfb, ncob, 1.0_dp, sinab(1, 1), ldab, &
    1212        73992 :                  sphi_b(1, sgfb), ldsb, 0.0_dp, work(1, 1), ldwork)
    1213              : 
    1214              :       CALL dgemm("T", "N", nsgfa, nsgfb, ncoa, 1.0_dp, sphi_a(1, sgfa), ldsa, &
    1215        73992 :                  work(1, 1), ldwork, 1.0_dp, sin_block(sgfa, sgfb), SIZE(sin_block, 1))
    1216              : 
    1217        73992 :    END SUBROUTINE contract_all
    1218              : 
    1219              : END MODULE qs_efield_berry
        

Generated by: LCOV version 2.0-1