Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Calculation of electric field contributions in TB
10 : !> \author JGH
11 : ! **************************************************************************************************
12 : MODULE efield_tb_methods
13 : USE atomic_kind_types, ONLY: atomic_kind_type,&
14 : get_atomic_kind_set
15 : USE cell_types, ONLY: cell_type,&
16 : pbc
17 : USE cp_control_types, ONLY: dft_control_type
18 : USE cp_dbcsr_api, ONLY: dbcsr_get_block_p,&
19 : dbcsr_iterator_blocks_left,&
20 : dbcsr_iterator_next_block,&
21 : dbcsr_iterator_start,&
22 : dbcsr_iterator_stop,&
23 : dbcsr_iterator_type,&
24 : dbcsr_p_type
25 : USE kinds, ONLY: dp
26 : USE kpoint_types, ONLY: get_kpoint_info,&
27 : kpoint_type
28 : USE mathconstants, ONLY: pi,&
29 : twopi
30 : USE message_passing, ONLY: mp_para_env_type
31 : USE particle_types, ONLY: particle_type
32 : USE qs_energy_types, ONLY: qs_energy_type
33 : USE qs_environment_types, ONLY: get_qs_env,&
34 : qs_environment_type,&
35 : set_qs_env
36 : USE qs_force_types, ONLY: qs_force_type
37 : USE qs_kind_types, ONLY: qs_kind_type
38 : USE qs_neighbor_list_types, ONLY: get_iterator_info,&
39 : neighbor_list_iterate,&
40 : neighbor_list_iterator_create,&
41 : neighbor_list_iterator_p_type,&
42 : neighbor_list_iterator_release,&
43 : neighbor_list_set_p_type
44 : USE qs_period_efield_types, ONLY: efield_berry_type,&
45 : init_efield_matrices
46 : USE qs_rho_types, ONLY: qs_rho_get,&
47 : qs_rho_type
48 : USE sap_kind_types, ONLY: release_sap_int,&
49 : sap_int_type
50 : USE virial_methods, ONLY: virial_pair_force
51 : USE virial_types, ONLY: virial_type
52 : USE xtb_coulomb, ONLY: xtb_dsint_list
53 : #include "./base/base_uses.f90"
54 :
55 : IMPLICIT NONE
56 :
57 : PRIVATE
58 :
59 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'efield_tb_methods'
60 :
61 : PUBLIC :: efield_tb_matrix
62 :
63 : CONTAINS
64 :
65 : ! **************************************************************************************************
66 : !> \brief ...
67 : !> \param qs_env ...
68 : !> \param ks_matrix ...
69 : !> \param rho ...
70 : !> \param mcharge ...
71 : !> \param energy ...
72 : !> \param calculate_forces ...
73 : !> \param just_energy ...
74 : ! **************************************************************************************************
75 17814 : SUBROUTINE efield_tb_matrix(qs_env, ks_matrix, rho, mcharge, energy, calculate_forces, just_energy)
76 :
77 : TYPE(qs_environment_type), POINTER :: qs_env
78 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: ks_matrix
79 : TYPE(qs_rho_type), POINTER :: rho
80 : REAL(dp), DIMENSION(:), INTENT(in) :: mcharge
81 : TYPE(qs_energy_type), POINTER :: energy
82 : LOGICAL, INTENT(in) :: calculate_forces, just_energy
83 :
84 : CHARACTER(len=*), PARAMETER :: routineN = 'efield_tb_matrix'
85 :
86 : INTEGER :: handle
87 : TYPE(dft_control_type), POINTER :: dft_control
88 :
89 17814 : CALL timeset(routineN, handle)
90 :
91 17814 : energy%efield = 0.0_dp
92 17814 : CALL get_qs_env(qs_env, dft_control=dft_control)
93 17814 : IF (dft_control%qs_control%dftb .OR. dft_control%qs_control%xtb) THEN
94 17814 : IF (dft_control%apply_period_efield) THEN
95 4292 : IF (dft_control%period_efield%displacement_field) THEN
96 332 : CALL dfield_tb_berry(qs_env, ks_matrix, rho, mcharge, energy, calculate_forces, just_energy)
97 : ELSE
98 3960 : CALL efield_tb_berry(qs_env, ks_matrix, rho, mcharge, energy, calculate_forces, just_energy)
99 : END IF
100 13522 : ELSE IF (dft_control%apply_efield) THEN
101 2180 : CALL efield_tb_local(qs_env, ks_matrix, rho, mcharge, energy, calculate_forces, just_energy)
102 11342 : ELSE IF (dft_control%apply_efield_field) THEN
103 0 : CPABORT("efield_filed")
104 : END IF
105 : ELSE
106 0 : CPABORT("This routine should only be called from TB")
107 : END IF
108 :
109 17814 : CALL timestop(handle)
110 :
111 17814 : END SUBROUTINE efield_tb_matrix
112 :
113 : ! **************************************************************************************************
114 : !> \brief ...
115 : !> \param qs_env ...
116 : !> \param ks_matrix ...
117 : !> \param rho ...
118 : !> \param mcharge ...
119 : !> \param energy ...
120 : !> \param calculate_forces ...
121 : !> \param just_energy ...
122 : ! **************************************************************************************************
123 2180 : SUBROUTINE efield_tb_local(qs_env, ks_matrix, rho, mcharge, energy, calculate_forces, just_energy)
124 : TYPE(qs_environment_type), POINTER :: qs_env
125 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: ks_matrix
126 : TYPE(qs_rho_type), POINTER :: rho
127 : REAL(dp), DIMENSION(:), INTENT(in) :: mcharge
128 : TYPE(qs_energy_type), POINTER :: energy
129 : LOGICAL, INTENT(in) :: calculate_forces, just_energy
130 :
131 : CHARACTER(LEN=*), PARAMETER :: routineN = 'efield_tb_local'
132 :
133 : INTEGER :: atom_a, atom_b, blk, handle, ia, icol, &
134 : idir, ikind, irow, ispin, jkind, &
135 : natom, nspin
136 2180 : INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, kind_of
137 : LOGICAL :: do_kpoints, found, use_virial
138 : REAL(dp) :: charge, fdir
139 : REAL(dp), DIMENSION(3) :: ci, fieldpol, fij, ria, rib
140 2180 : REAL(dp), DIMENSION(:, :), POINTER :: ds_block, ks_block, p_block, s_block
141 2180 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
142 : TYPE(cell_type), POINTER :: cell
143 : TYPE(dbcsr_iterator_type) :: iter
144 2180 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_p, matrix_s
145 : TYPE(dft_control_type), POINTER :: dft_control
146 : TYPE(mp_para_env_type), POINTER :: para_env
147 2180 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
148 2180 : TYPE(qs_force_type), DIMENSION(:), POINTER :: force
149 2180 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
150 : TYPE(virial_type), POINTER :: virial
151 :
152 2180 : CALL timeset(routineN, handle)
153 :
154 2180 : CALL get_qs_env(qs_env, dft_control=dft_control, cell=cell, particle_set=particle_set)
155 2180 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, energy=energy, para_env=para_env)
156 2180 : CALL get_qs_env(qs_env=qs_env, do_kpoints=do_kpoints, virial=virial)
157 2180 : IF (do_kpoints) THEN
158 0 : CPABORT("Local electric field with kpoints not possible. Use Berry phase periodic version")
159 : END IF
160 : ! disable stress calculation
161 2180 : use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
162 : IF (use_virial) THEN
163 0 : CPABORT("Stress tensor for non-periodic E-field not possible")
164 : END IF
165 :
166 : fieldpol = dft_control%efield_fields(1)%efield%polarisation* &
167 8720 : dft_control%efield_fields(1)%efield%strength
168 :
169 2180 : natom = SIZE(particle_set)
170 2180 : ci = 0.0_dp
171 10568 : DO ia = 1, natom
172 8388 : charge = mcharge(ia)
173 33552 : ria = particle_set(ia)%r
174 33552 : ria = pbc(ria, cell)
175 35732 : ci(:) = ci(:) + charge*ria(:)
176 : END DO
177 8720 : energy%efield = -SUM(ci(:)*fieldpol(:))
178 :
179 2180 : IF (.NOT. just_energy) THEN
180 :
181 2180 : IF (calculate_forces) THEN
182 32 : CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, force=force)
183 32 : CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, kind_of=kind_of)
184 32 : IF (para_env%mepos == 0) THEN
185 72 : DO ia = 1, natom
186 56 : charge = mcharge(ia)
187 56 : ikind = kind_of(ia)
188 56 : atom_a = atom_of_kind(ia)
189 240 : force(ikind)%efield(1:3, atom_a) = -charge*fieldpol(:)
190 : END DO
191 : ELSE
192 72 : DO ia = 1, natom
193 56 : ikind = kind_of(ia)
194 56 : atom_a = atom_of_kind(ia)
195 240 : force(ikind)%efield(1:3, atom_a) = 0.0_dp
196 : END DO
197 : END IF
198 32 : CALL qs_rho_get(rho, rho_ao=matrix_p)
199 : END IF
200 :
201 : ! Update KS matrix
202 2180 : nspin = SIZE(ks_matrix, 1)
203 2180 : NULLIFY (matrix_s)
204 2180 : CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s)
205 2180 : CALL dbcsr_iterator_start(iter, matrix_s(1)%matrix)
206 12687 : DO WHILE (dbcsr_iterator_blocks_left(iter))
207 10507 : NULLIFY (ks_block, s_block, p_block)
208 10507 : CALL dbcsr_iterator_next_block(iter, irow, icol, s_block, blk)
209 42028 : ria = particle_set(irow)%r
210 42028 : ria = pbc(ria, cell)
211 42028 : rib = particle_set(icol)%r
212 42028 : rib = pbc(rib, cell)
213 42028 : fdir = 0.5_dp*SUM(fieldpol(1:3)*(ria(1:3) + rib(1:3)))
214 21014 : DO ispin = 1, nspin
215 : CALL dbcsr_get_block_p(matrix=ks_matrix(ispin, 1)%matrix, &
216 10507 : row=irow, col=icol, BLOCK=ks_block, found=found)
217 274575 : ks_block = ks_block + fdir*s_block
218 31521 : CPASSERT(found)
219 : END DO
220 12687 : IF (calculate_forces) THEN
221 136 : ikind = kind_of(irow)
222 136 : jkind = kind_of(icol)
223 136 : atom_a = atom_of_kind(irow)
224 136 : atom_b = atom_of_kind(icol)
225 136 : fij = 0.0_dp
226 272 : DO ispin = 1, nspin
227 : CALL dbcsr_get_block_p(matrix=matrix_p(ispin)%matrix, &
228 136 : row=irow, col=icol, BLOCK=p_block, found=found)
229 136 : CPASSERT(found)
230 816 : DO idir = 1, 3
231 : CALL dbcsr_get_block_p(matrix=matrix_s(idir + 1)%matrix, &
232 408 : row=irow, col=icol, BLOCK=ds_block, found=found)
233 408 : CPASSERT(found)
234 6502 : fij(idir) = fij(idir) + SUM(p_block*ds_block)
235 : END DO
236 : END DO
237 544 : fdir = SUM(ria(1:3)*fieldpol(1:3))
238 544 : force(ikind)%efield(1:3, atom_a) = force(ikind)%efield(1:3, atom_a) + fdir*fij(1:3)
239 544 : force(jkind)%efield(1:3, atom_b) = force(jkind)%efield(1:3, atom_b) - fdir*fij(1:3)
240 544 : fdir = SUM(rib(1:3)*fieldpol(1:3))
241 544 : force(ikind)%efield(1:3, atom_a) = force(ikind)%efield(1:3, atom_a) + fdir*fij(1:3)
242 544 : force(jkind)%efield(1:3, atom_b) = force(jkind)%efield(1:3, atom_b) - fdir*fij(1:3)
243 : END IF
244 : END DO
245 2180 : CALL dbcsr_iterator_stop(iter)
246 :
247 2180 : IF (calculate_forces) THEN
248 120 : DO ikind = 1, SIZE(atomic_kind_set)
249 1016 : CALL para_env%sum(force(ikind)%efield)
250 : END DO
251 : END IF
252 :
253 : END IF
254 :
255 2180 : CALL timestop(handle)
256 :
257 4360 : END SUBROUTINE efield_tb_local
258 :
259 : ! **************************************************************************************************
260 : !> \brief ...
261 : !> \param qs_env ...
262 : !> \param ks_matrix ...
263 : !> \param rho ...
264 : !> \param mcharge ...
265 : !> \param energy ...
266 : !> \param calculate_forces ...
267 : !> \param just_energy ...
268 : ! **************************************************************************************************
269 3960 : SUBROUTINE efield_tb_berry(qs_env, ks_matrix, rho, mcharge, energy, calculate_forces, just_energy)
270 : TYPE(qs_environment_type), POINTER :: qs_env
271 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: ks_matrix
272 : TYPE(qs_rho_type), POINTER :: rho
273 : REAL(dp), DIMENSION(:), INTENT(in) :: mcharge
274 : TYPE(qs_energy_type), POINTER :: energy
275 : LOGICAL, INTENT(in) :: calculate_forces, just_energy
276 :
277 : CHARACTER(LEN=*), PARAMETER :: routineN = 'efield_tb_berry'
278 :
279 : COMPLEX(KIND=dp) :: zdeta
280 : COMPLEX(KIND=dp), DIMENSION(3) :: zi(3)
281 : INTEGER :: atom_a, atom_b, blk, handle, ia, iac, &
282 : iatom, ic, icol, idir, ikind, irow, &
283 : is, ispin, jatom, jkind, natom, nimg, &
284 : nkind, nspin
285 3960 : INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, kind_of
286 : INTEGER, DIMENSION(3) :: cellind
287 3960 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
288 : LOGICAL :: found, use_virial
289 : REAL(KIND=dp) :: charge, dd, dr, fdir, fi
290 : REAL(KIND=dp), DIMENSION(3) :: fieldpol, fij, forcea, fpolvec, kvec, &
291 : qi, rab, ria, rib, rij
292 : REAL(KIND=dp), DIMENSION(3, 3) :: hmat
293 3960 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: ds_block, ks_block, p_block, s_block
294 3960 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: dsint
295 3960 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
296 : TYPE(cell_type), POINTER :: cell
297 : TYPE(dbcsr_iterator_type) :: iter
298 3960 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_p, matrix_s
299 : TYPE(dft_control_type), POINTER :: dft_control
300 : TYPE(kpoint_type), POINTER :: kpoints
301 : TYPE(mp_para_env_type), POINTER :: para_env
302 : TYPE(neighbor_list_iterator_p_type), &
303 3960 : DIMENSION(:), POINTER :: nl_iterator
304 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
305 3960 : POINTER :: sab_orb
306 3960 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
307 3960 : TYPE(qs_force_type), DIMENSION(:), POINTER :: force
308 3960 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
309 3960 : TYPE(sap_int_type), DIMENSION(:), POINTER :: sap_int
310 : TYPE(virial_type), POINTER :: virial
311 :
312 3960 : CALL timeset(routineN, handle)
313 :
314 3960 : NULLIFY (dft_control, cell, particle_set)
315 : CALL get_qs_env(qs_env, dft_control=dft_control, cell=cell, &
316 3960 : particle_set=particle_set, virial=virial)
317 3960 : NULLIFY (qs_kind_set, para_env, sab_orb)
318 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
319 3960 : energy=energy, para_env=para_env, sab_orb=sab_orb)
320 :
321 : ! calculate stress only if forces requested also
322 4076 : use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
323 124 : use_virial = use_virial .AND. calculate_forces
324 :
325 15840 : fieldpol = dft_control%period_efield%polarisation
326 27720 : fieldpol = fieldpol/SQRT(DOT_PRODUCT(fieldpol, fieldpol))
327 15840 : fieldpol = -fieldpol*dft_control%period_efield%strength
328 51480 : hmat = cell%hmat(:, :)/twopi
329 15840 : DO idir = 1, 3
330 15840 : fpolvec(idir) = fieldpol(1)*hmat(1, idir) + fieldpol(2)*hmat(2, idir) + fieldpol(3)*hmat(3, idir)
331 : END DO
332 :
333 3960 : natom = SIZE(particle_set)
334 3960 : nspin = SIZE(ks_matrix, 1)
335 :
336 15840 : zi(:) = CMPLX(1._dp, 0._dp, dp)
337 18474 : DO ia = 1, natom
338 14514 : charge = mcharge(ia)
339 58056 : ria = particle_set(ia)%r
340 62016 : DO idir = 1, 3
341 174168 : kvec(:) = twopi*cell%h_inv(idir, :)
342 174168 : dd = SUM(kvec(:)*ria(:))
343 43542 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)**charge
344 58056 : zi(idir) = zi(idir)*zdeta
345 : END DO
346 : END DO
347 15840 : qi = AIMAG(LOG(zi))
348 15840 : energy%efield = -SUM(fpolvec(:)*qi(:))
349 :
350 3960 : IF (.NOT. just_energy) THEN
351 3960 : CALL get_qs_env(qs_env=qs_env, matrix_s_kp=matrix_s)
352 3960 : CALL qs_rho_get(rho, rho_ao_kp=matrix_p)
353 :
354 3960 : nimg = dft_control%nimages
355 3960 : NULLIFY (cell_to_index)
356 3960 : IF (nimg > 1) THEN
357 1858 : NULLIFY (kpoints)
358 1858 : CALL get_qs_env(qs_env=qs_env, kpoints=kpoints)
359 1858 : CALL get_kpoint_info(kpoint=kpoints, cell_to_index=cell_to_index)
360 : END IF
361 :
362 3960 : IF (calculate_forces) THEN
363 46 : CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, force=force)
364 46 : CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, kind_of=kind_of)
365 46 : IF (para_env%mepos == 0) THEN
366 94 : DO ia = 1, natom
367 71 : charge = -mcharge(ia)
368 71 : iatom = atom_of_kind(ia)
369 71 : ikind = kind_of(ia)
370 284 : force(ikind)%efield(:, iatom) = fieldpol(:)*charge
371 94 : IF (use_virial) THEN
372 64 : ria = particle_set(ia)%r
373 64 : ria = pbc(ria, cell)
374 64 : forcea(1:3) = fieldpol(1:3)*charge
375 16 : CALL virial_pair_force(virial%pv_virial, -0.5_dp, forcea, ria)
376 16 : CALL virial_pair_force(virial%pv_virial, -0.5_dp, ria, forcea)
377 : END IF
378 : END DO
379 : ELSE
380 94 : DO ia = 1, natom
381 71 : iatom = atom_of_kind(ia)
382 71 : ikind = kind_of(ia)
383 307 : force(ikind)%efield(:, iatom) = 0.0_dp
384 : END DO
385 : END IF
386 : END IF
387 :
388 3960 : IF (nimg == 1) THEN
389 : ! no k-points; all matrices have been transformed to periodic bsf
390 2102 : CALL dbcsr_iterator_start(iter, matrix_s(1, 1)%matrix)
391 11294 : DO WHILE (dbcsr_iterator_blocks_left(iter))
392 9192 : CALL dbcsr_iterator_next_block(iter, irow, icol, s_block, blk)
393 :
394 9192 : fdir = 0.0_dp
395 36768 : ria = particle_set(irow)%r
396 36768 : rib = particle_set(icol)%r
397 36768 : DO idir = 1, 3
398 110304 : kvec(:) = twopi*cell%h_inv(idir, :)
399 110304 : dd = SUM(kvec(:)*ria(:))
400 27576 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
401 27576 : fdir = fdir + fpolvec(idir)*AIMAG(LOG(zdeta))
402 110304 : dd = SUM(kvec(:)*rib(:))
403 27576 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
404 36768 : fdir = fdir + fpolvec(idir)*AIMAG(LOG(zdeta))
405 : END DO
406 :
407 22756 : DO is = 1, nspin
408 13564 : NULLIFY (ks_block)
409 : CALL dbcsr_get_block_p(matrix=ks_matrix(is, 1)%matrix, &
410 13564 : row=irow, col=icol, block=ks_block, found=found)
411 13564 : CPASSERT(found)
412 355608 : ks_block = ks_block + 0.5_dp*fdir*s_block
413 : END DO
414 11294 : IF (calculate_forces) THEN
415 82 : ikind = kind_of(irow)
416 82 : jkind = kind_of(icol)
417 82 : atom_a = atom_of_kind(irow)
418 82 : atom_b = atom_of_kind(icol)
419 82 : fij = 0.0_dp
420 208 : DO ispin = 1, nspin
421 : CALL dbcsr_get_block_p(matrix=matrix_p(ispin, 1)%matrix, &
422 126 : row=irow, col=icol, BLOCK=p_block, found=found)
423 126 : CPASSERT(found)
424 712 : DO idir = 1, 3
425 : CALL dbcsr_get_block_p(matrix=matrix_s(idir + 1, 1)%matrix, &
426 378 : row=irow, col=icol, BLOCK=ds_block, found=found)
427 378 : CPASSERT(found)
428 5076 : fij(idir) = fij(idir) + SUM(p_block*ds_block)
429 : END DO
430 : END DO
431 328 : force(ikind)%efield(1:3, atom_a) = force(ikind)%efield(1:3, atom_a) + fdir*fij(1:3)
432 328 : force(jkind)%efield(1:3, atom_b) = force(jkind)%efield(1:3, atom_b) - fdir*fij(1:3)
433 : END IF
434 : END DO
435 2102 : CALL dbcsr_iterator_stop(iter)
436 : !
437 : ! stress tensor for Gamma point needs to recalculate overlap integral derivatives
438 : !
439 2102 : IF (use_virial) THEN
440 : ! derivative overlap integral (non collapsed)
441 4 : NULLIFY (sap_int)
442 4 : IF (dft_control%qs_control%dftb) THEN
443 0 : CPABORT("DFTB stress tensor for periodic efield not implemented")
444 4 : ELSEIF (dft_control%qs_control%xtb) THEN
445 4 : CALL xtb_dsint_list(qs_env, sap_int)
446 : ELSE
447 0 : CPABORT("TB method unknown")
448 : END IF
449 : !
450 4 : CALL get_qs_env(qs_env, nkind=nkind)
451 16 : DO ikind = 1, nkind
452 52 : DO jkind = 1, nkind
453 36 : iac = ikind + nkind*(jkind - 1)
454 36 : IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
455 48 : DO ia = 1, sap_int(iac)%nalist
456 18 : IF (.NOT. ASSOCIATED(sap_int(iac)%alist(ia)%clist)) CYCLE
457 18 : iatom = sap_int(iac)%alist(ia)%aatom
458 1394 : DO ic = 1, sap_int(iac)%alist(ia)%nclist
459 1340 : jatom = sap_int(iac)%alist(ia)%clist(ic)%catom
460 5360 : rij = sap_int(iac)%alist(ia)%clist(ic)%rac
461 5360 : dr = SQRT(SUM(rij(:)**2))
462 1358 : IF (dr > 1.e-6_dp) THEN
463 1332 : dsint => sap_int(iac)%alist(ia)%clist(ic)%acint
464 1332 : icol = MAX(iatom, jatom)
465 1332 : irow = MIN(iatom, jatom)
466 3636 : IF (irow == iatom) rij = -rij
467 1332 : fdir = 0.0_dp
468 5328 : ria = particle_set(irow)%r
469 5328 : rib = particle_set(icol)%r
470 5328 : DO idir = 1, 3
471 15984 : kvec(:) = twopi*cell%h_inv(idir, :)
472 15984 : dd = SUM(kvec(:)*ria(:))
473 3996 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
474 3996 : fdir = fdir + fpolvec(idir)*AIMAG(LOG(zdeta))
475 15984 : dd = SUM(kvec(:)*rib(:))
476 3996 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
477 5328 : fdir = fdir + fpolvec(idir)*AIMAG(LOG(zdeta))
478 : END DO
479 1332 : fi = 1.0_dp
480 1332 : IF (iatom == jatom) fi = 0.5_dp
481 3330 : DO ispin = 1, nspin
482 1998 : NULLIFY (p_block)
483 : CALL dbcsr_get_block_p(matrix=matrix_p(ispin, 1)%matrix, &
484 1998 : row=irow, col=icol, block=p_block, found=found)
485 1998 : CPASSERT(found)
486 1998 : fij = 0.0_dp
487 7992 : DO idir = 1, 3
488 7992 : IF (irow == iatom) THEN
489 40176 : fij(idir) = SUM(p_block*dsint(:, :, idir))
490 : ELSE
491 31662 : fij(idir) = SUM(TRANSPOSE(p_block)*dsint(:, :, idir))
492 : END IF
493 : END DO
494 5454 : IF (irow == iatom) fij = -fij
495 11322 : CALL virial_pair_force(virial%pv_virial, fi, fdir*fij(1:3), rij)
496 : END DO
497 : END IF
498 : END DO
499 : END DO
500 : END DO
501 : END DO
502 4 : CALL release_sap_int(sap_int)
503 : END IF
504 : ELSE
505 1858 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
506 494311 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
507 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, &
508 492453 : iatom=iatom, jatom=jatom, r=rab, cell=cellind)
509 :
510 492453 : icol = MAX(iatom, jatom)
511 492453 : irow = MIN(iatom, jatom)
512 :
513 492453 : ic = cell_to_index(cellind(1), cellind(2), cellind(3))
514 492453 : CPASSERT(ic > 0)
515 :
516 492453 : fdir = 0.0_dp
517 1969812 : ria = particle_set(irow)%r
518 1969812 : rib = particle_set(icol)%r
519 1969812 : DO idir = 1, 3
520 5909436 : kvec(:) = twopi*cell%h_inv(idir, :)
521 5909436 : dd = SUM(kvec(:)*ria(:))
522 1477359 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
523 1477359 : fdir = fdir + fpolvec(idir)*AIMAG(LOG(zdeta))
524 5909436 : dd = SUM(kvec(:)*rib(:))
525 1477359 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
526 1969812 : fdir = fdir + fpolvec(idir)*AIMAG(LOG(zdeta))
527 : END DO
528 :
529 492453 : NULLIFY (s_block)
530 : CALL dbcsr_get_block_p(matrix=matrix_s(1, ic)%matrix, &
531 492453 : row=irow, col=icol, block=s_block, found=found)
532 492453 : CPASSERT(found)
533 1169156 : DO is = 1, nspin
534 676703 : NULLIFY (ks_block)
535 : CALL dbcsr_get_block_p(matrix=ks_matrix(is, ic)%matrix, &
536 676703 : row=irow, col=icol, block=ks_block, found=found)
537 676703 : CPASSERT(found)
538 15851147 : ks_block = ks_block + 0.5_dp*fdir*s_block
539 : END DO
540 494311 : IF (calculate_forces) THEN
541 3323 : atom_a = atom_of_kind(iatom)
542 3323 : atom_b = atom_of_kind(jatom)
543 3323 : fij = 0.0_dp
544 7986 : DO ispin = 1, nspin
545 : CALL dbcsr_get_block_p(matrix=matrix_p(ispin, ic)%matrix, &
546 4663 : row=irow, col=icol, BLOCK=p_block, found=found)
547 4663 : CPASSERT(found)
548 26638 : DO idir = 1, 3
549 : CALL dbcsr_get_block_p(matrix=matrix_s(idir + 1, ic)%matrix, &
550 13989 : row=irow, col=icol, BLOCK=ds_block, found=found)
551 13989 : CPASSERT(found)
552 176149 : fij(idir) = fij(idir) + SUM(p_block*ds_block)
553 : END DO
554 : END DO
555 9197 : IF (irow == iatom) fij = -fij
556 13292 : force(ikind)%efield(1:3, atom_a) = force(ikind)%efield(1:3, atom_a) - fdir*fij(1:3)
557 13292 : force(jkind)%efield(1:3, atom_b) = force(jkind)%efield(1:3, atom_b) + fdir*fij(1:3)
558 3323 : IF (use_virial) THEN
559 5360 : dr = SQRT(SUM(rab(:)**2))
560 1340 : IF (dr > 1.e-6_dp) THEN
561 1332 : fi = 1.0_dp
562 1332 : IF (iatom == jatom) fi = 0.5_dp
563 5328 : CALL virial_pair_force(virial%pv_virial, fi, -fdir*fij(1:3), rab)
564 : END IF
565 : END IF
566 : END IF
567 : END DO
568 1858 : CALL neighbor_list_iterator_release(nl_iterator)
569 : END IF
570 :
571 3960 : IF (calculate_forces) THEN
572 154 : DO ikind = 1, SIZE(atomic_kind_set)
573 1290 : CALL para_env%sum(force(ikind)%efield)
574 : END DO
575 : END IF
576 :
577 : END IF
578 :
579 3960 : CALL timestop(handle)
580 :
581 7920 : END SUBROUTINE efield_tb_berry
582 :
583 : ! **************************************************************************************************
584 : !> \brief ...
585 : !> \param qs_env ...
586 : !> \param ks_matrix ...
587 : !> \param rho ...
588 : !> \param mcharge ...
589 : !> \param energy ...
590 : !> \param calculate_forces ...
591 : !> \param just_energy ...
592 : ! **************************************************************************************************
593 332 : SUBROUTINE dfield_tb_berry(qs_env, ks_matrix, rho, mcharge, energy, calculate_forces, just_energy)
594 : TYPE(qs_environment_type), POINTER :: qs_env
595 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: ks_matrix
596 : TYPE(qs_rho_type), POINTER :: rho
597 : REAL(dp), DIMENSION(:), INTENT(in) :: mcharge
598 : TYPE(qs_energy_type), POINTER :: energy
599 : LOGICAL, INTENT(in) :: calculate_forces, just_energy
600 :
601 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dfield_tb_berry'
602 :
603 : COMPLEX(KIND=dp) :: zdeta
604 : COMPLEX(KIND=dp), DIMENSION(3) :: zi(3)
605 : INTEGER :: atom_a, atom_b, blk, handle, i, ia, &
606 : iatom, ic, icol, idir, ikind, irow, &
607 : is, ispin, jatom, jkind, natom, nimg, &
608 : nspin
609 332 : INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, kind_of
610 : INTEGER, DIMENSION(3) :: cellind
611 332 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
612 : LOGICAL :: found, use_virial
613 : REAL(KIND=dp) :: charge, dd, ener_field, fdir, omega
614 : REAL(KIND=dp), DIMENSION(3) :: ci, cqi, dfilter, di, fieldpol, fij, &
615 : hdi, kvec, qi, rab, ria, rib
616 : REAL(KIND=dp), DIMENSION(3, 3) :: hmat
617 332 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: ds_block, ks_block, p_block, s_block
618 332 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
619 : TYPE(cell_type), POINTER :: cell
620 : TYPE(dbcsr_iterator_type) :: iter
621 332 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_p, matrix_s
622 : TYPE(dft_control_type), POINTER :: dft_control
623 : TYPE(efield_berry_type), POINTER :: efield
624 : TYPE(kpoint_type), POINTER :: kpoints
625 : TYPE(mp_para_env_type), POINTER :: para_env
626 : TYPE(neighbor_list_iterator_p_type), &
627 332 : DIMENSION(:), POINTER :: nl_iterator
628 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
629 332 : POINTER :: sab_orb
630 332 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
631 332 : TYPE(qs_force_type), DIMENSION(:), POINTER :: force
632 332 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
633 : TYPE(virial_type), POINTER :: virial
634 :
635 332 : CALL timeset(routineN, handle)
636 :
637 332 : NULLIFY (dft_control, cell, particle_set)
638 : CALL get_qs_env(qs_env, dft_control=dft_control, cell=cell, &
639 332 : particle_set=particle_set, virial=virial)
640 332 : NULLIFY (qs_kind_set, para_env, sab_orb)
641 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
642 332 : efield=efield, energy=energy, para_env=para_env, sab_orb=sab_orb)
643 :
644 : ! efield history
645 332 : CALL init_efield_matrices(efield)
646 332 : CALL set_qs_env(qs_env, efield=efield)
647 :
648 : ! calculate stress only if forces requested also
649 332 : use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
650 0 : use_virial = use_virial .AND. calculate_forces
651 : ! disable stress calculation
652 : IF (use_virial) THEN
653 0 : CPABORT("Stress tensor for periodic D-field not implemented")
654 : END IF
655 :
656 1328 : dfilter(1:3) = dft_control%period_efield%d_filter(1:3)
657 :
658 1328 : fieldpol = dft_control%period_efield%polarisation
659 2324 : fieldpol = fieldpol/SQRT(DOT_PRODUCT(fieldpol, fieldpol))
660 1328 : fieldpol = fieldpol*dft_control%period_efield%strength
661 :
662 332 : omega = cell%deth
663 4316 : hmat = cell%hmat(:, :)/twopi
664 :
665 332 : natom = SIZE(particle_set)
666 332 : nspin = SIZE(ks_matrix, 1)
667 :
668 1328 : zi(:) = CMPLX(1._dp, 0._dp, dp)
669 996 : DO ia = 1, natom
670 664 : charge = mcharge(ia)
671 2656 : ria = particle_set(ia)%r
672 2988 : DO idir = 1, 3
673 7968 : kvec(:) = twopi*cell%h_inv(idir, :)
674 7968 : dd = SUM(kvec(:)*ria(:))
675 1992 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)**charge
676 2656 : zi(idir) = zi(idir)*zdeta
677 : END DO
678 : END DO
679 1328 : qi = AIMAG(LOG(zi))
680 :
681 : ! make sure the total normalized polarization is within [-1:1]
682 1328 : DO idir = 1, 3
683 996 : cqi(idir) = qi(idir)/omega
684 996 : IF (cqi(idir) > pi) cqi(idir) = cqi(idir) - twopi
685 996 : IF (cqi(idir) < -pi) cqi(idir) = cqi(idir) + twopi
686 : ! now check for log branch
687 996 : IF (calculate_forces) THEN
688 30 : IF (ABS(efield%polarisation(idir) - cqi(idir)) > pi) THEN
689 0 : di(idir) = (efield%polarisation(idir) - cqi(idir))/pi
690 0 : DO i = 1, 10
691 0 : cqi(idir) = cqi(idir) + SIGN(1.0_dp, di(idir))*twopi
692 0 : IF (ABS(efield%polarisation(idir) - cqi(idir)) < pi) EXIT
693 : END DO
694 : END IF
695 : END IF
696 1328 : cqi(idir) = cqi(idir)*omega
697 : END DO
698 1328 : DO idir = 1, 3
699 996 : ci(idir) = 0.0_dp
700 4316 : DO i = 1, 3
701 3984 : ci(idir) = ci(idir) + hmat(idir, i)*cqi(i)
702 : END DO
703 : END DO
704 : ! update the references
705 332 : IF (calculate_forces) THEN
706 40 : ener_field = SUM(ci)
707 : ! check for smoothness of energy surface
708 130 : IF (ABS(efield%field_energy - ener_field) > pi*ABS(SUM(hmat))) THEN
709 0 : CPWARN("Large change of e-field energy detected. Correct for non-smooth energy surface")
710 : END IF
711 10 : efield%field_energy = ener_field
712 40 : efield%polarisation(:) = cqi(:)/omega
713 : END IF
714 :
715 : ! Energy
716 332 : ener_field = 0.0_dp
717 1328 : DO idir = 1, 3
718 1328 : ener_field = ener_field + dfilter(idir)*(fieldpol(idir) - 2._dp*twopi/omega*ci(idir))**2
719 : END DO
720 332 : energy%efield = 0.25_dp/twopi*ener_field
721 :
722 332 : IF (.NOT. just_energy) THEN
723 1328 : di(:) = -(fieldpol(:) - 2._dp*twopi/omega*ci(:))*dfilter(:)/omega
724 :
725 332 : CALL get_qs_env(qs_env=qs_env, matrix_s_kp=matrix_s)
726 332 : CALL qs_rho_get(rho, rho_ao_kp=matrix_p)
727 :
728 332 : nimg = dft_control%nimages
729 332 : NULLIFY (cell_to_index)
730 332 : IF (nimg > 1) THEN
731 0 : NULLIFY (kpoints)
732 0 : CALL get_qs_env(qs_env=qs_env, kpoints=kpoints)
733 0 : CALL get_kpoint_info(kpoint=kpoints, cell_to_index=cell_to_index)
734 : END IF
735 :
736 332 : IF (calculate_forces) THEN
737 10 : CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, force=force)
738 10 : CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, kind_of=kind_of)
739 10 : IF (para_env%mepos == 0) THEN
740 15 : DO ia = 1, natom
741 10 : charge = mcharge(ia)
742 10 : iatom = atom_of_kind(ia)
743 10 : ikind = kind_of(ia)
744 45 : force(ikind)%efield(:, iatom) = force(ikind)%efield(:, iatom) + di(:)*charge
745 : END DO
746 : END IF
747 : END IF
748 :
749 332 : IF (nimg == 1) THEN
750 : ! no k-points; all matrices have been transformed to periodic bsf
751 332 : CALL dbcsr_iterator_start(iter, matrix_s(1, 1)%matrix)
752 830 : DO WHILE (dbcsr_iterator_blocks_left(iter))
753 498 : CALL dbcsr_iterator_next_block(iter, irow, icol, s_block, blk)
754 :
755 1992 : DO idir = 1, 3
756 6474 : hdi(idir) = -SUM(di(1:3)*hmat(1:3, idir))
757 : END DO
758 498 : fdir = 0.0_dp
759 1992 : ria = particle_set(irow)%r
760 1992 : rib = particle_set(icol)%r
761 1992 : DO idir = 1, 3
762 5976 : kvec(:) = twopi*cell%h_inv(idir, :)
763 5976 : dd = SUM(kvec(:)*ria(:))
764 1494 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
765 1494 : fdir = fdir + hdi(idir)*AIMAG(LOG(zdeta))
766 5976 : dd = SUM(kvec(:)*rib(:))
767 1494 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
768 1992 : fdir = fdir + hdi(idir)*AIMAG(LOG(zdeta))
769 : END DO
770 :
771 996 : DO is = 1, nspin
772 498 : NULLIFY (ks_block)
773 : CALL dbcsr_get_block_p(matrix=ks_matrix(is, 1)%matrix, &
774 498 : row=irow, col=icol, block=ks_block, found=found)
775 498 : CPASSERT(found)
776 14110 : ks_block = ks_block + 0.5_dp*fdir*s_block
777 : END DO
778 830 : IF (calculate_forces) THEN
779 15 : ikind = kind_of(irow)
780 15 : jkind = kind_of(icol)
781 15 : atom_a = atom_of_kind(irow)
782 15 : atom_b = atom_of_kind(icol)
783 15 : fij = 0.0_dp
784 30 : DO ispin = 1, nspin
785 : CALL dbcsr_get_block_p(matrix=matrix_p(ispin, 1)%matrix, &
786 15 : row=irow, col=icol, BLOCK=p_block, found=found)
787 15 : CPASSERT(found)
788 90 : DO idir = 1, 3
789 : CALL dbcsr_get_block_p(matrix=matrix_s(idir + 1, 1)%matrix, &
790 45 : row=irow, col=icol, BLOCK=ds_block, found=found)
791 45 : CPASSERT(found)
792 675 : fij(idir) = fij(idir) + SUM(p_block*ds_block)
793 : END DO
794 : END DO
795 60 : force(ikind)%efield(1:3, atom_a) = force(ikind)%efield(1:3, atom_a) + fdir*fij(1:3)
796 60 : force(jkind)%efield(1:3, atom_b) = force(jkind)%efield(1:3, atom_b) - fdir*fij(1:3)
797 : END IF
798 :
799 : END DO
800 332 : CALL dbcsr_iterator_stop(iter)
801 : ELSE
802 0 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
803 0 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
804 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, &
805 0 : iatom=iatom, jatom=jatom, r=rab, cell=cellind)
806 :
807 0 : icol = MAX(iatom, jatom)
808 0 : irow = MIN(iatom, jatom)
809 :
810 0 : ic = cell_to_index(cellind(1), cellind(2), cellind(3))
811 0 : CPASSERT(ic > 0)
812 :
813 0 : DO idir = 1, 3
814 0 : hdi(idir) = -SUM(di(1:3)*hmat(1:3, idir))
815 : END DO
816 0 : fdir = 0.0_dp
817 0 : ria = particle_set(irow)%r
818 0 : rib = particle_set(icol)%r
819 0 : DO idir = 1, 3
820 0 : kvec(:) = twopi*cell%h_inv(idir, :)
821 0 : dd = SUM(kvec(:)*ria(:))
822 0 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
823 0 : fdir = fdir + hdi(idir)*AIMAG(LOG(zdeta))
824 0 : dd = SUM(kvec(:)*rib(:))
825 0 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)
826 0 : fdir = fdir + hdi(idir)*AIMAG(LOG(zdeta))
827 : END DO
828 :
829 0 : NULLIFY (s_block)
830 : CALL dbcsr_get_block_p(matrix=matrix_s(1, ic)%matrix, &
831 0 : row=irow, col=icol, block=s_block, found=found)
832 0 : CPASSERT(found)
833 0 : DO is = 1, nspin
834 0 : NULLIFY (ks_block)
835 : CALL dbcsr_get_block_p(matrix=ks_matrix(is, ic)%matrix, &
836 0 : row=irow, col=icol, block=ks_block, found=found)
837 0 : CPASSERT(found)
838 0 : ks_block = ks_block + 0.5_dp*fdir*s_block
839 : END DO
840 0 : IF (calculate_forces) THEN
841 0 : atom_a = atom_of_kind(iatom)
842 0 : atom_b = atom_of_kind(jatom)
843 0 : fij = 0.0_dp
844 0 : DO ispin = 1, nspin
845 : CALL dbcsr_get_block_p(matrix=matrix_p(ispin, ic)%matrix, &
846 0 : row=irow, col=icol, BLOCK=p_block, found=found)
847 0 : CPASSERT(found)
848 0 : DO idir = 1, 3
849 : CALL dbcsr_get_block_p(matrix=matrix_s(idir + 1, ic)%matrix, &
850 0 : row=irow, col=icol, BLOCK=ds_block, found=found)
851 0 : CPASSERT(found)
852 0 : fij(idir) = fij(idir) + SUM(p_block*ds_block)
853 : END DO
854 : END DO
855 0 : IF (irow == iatom) fij = -fij
856 0 : force(ikind)%efield(1:3, atom_a) = force(ikind)%efield(1:3, atom_a) - fdir*fij(1:3)
857 0 : force(jkind)%efield(1:3, atom_b) = force(jkind)%efield(1:3, atom_b) + fdir*fij(1:3)
858 : END IF
859 :
860 : END DO
861 0 : CALL neighbor_list_iterator_release(nl_iterator)
862 : END IF
863 :
864 : END IF
865 :
866 332 : CALL timestop(handle)
867 :
868 664 : END SUBROUTINE dfield_tb_berry
869 :
870 : END MODULE efield_tb_methods
|