(git:ed6f26b)
Loading...
Searching...
No Matches
se_fock_matrix_coulomb.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Module that collects all Coulomb parts of the fock matrix construction
10!>
11!> \author Teodoro Laino (05.2009) [tlaino] - split and module reorganization
12!> \par History
13!> Teodoro Laino (04.2008) [tlaino] - University of Zurich : d-orbitals
14!> Teodoro Laino (09.2008) [tlaino] - University of Zurich : Speed-up
15!> Teodoro Laino (09.2008) [tlaino] - University of Zurich : Periodic SE
16!> Teodoro Laino (05.2009) [tlaino] - Stress Tensor
17!>
18! **************************************************************************************************
22 USE atprop_types, ONLY: atprop_type
23 USE cell_types, ONLY: cell_type
26 USE cp_dbcsr_api, ONLY: dbcsr_add,&
31 dbcsr_set,&
43 USE ewald_pw_types, ONLY: ewald_pw_get,&
48 USE input_constants, ONLY: &
53 USE kinds, ONLY: dp
65 USE qs_kind_types, ONLY: get_qs_kind,&
73 USE se_fock_matrix_integrals, ONLY: &
94 USE virial_types, ONLY: virial_type
95#include "./base/base_uses.f90"
96
97 IMPLICIT NONE
98 PRIVATE
99
100 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'se_fock_matrix_coulomb'
101 LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .false.
102
105
106CONTAINS
107
108! **************************************************************************************************
109!> \brief Construction of the Coulomb part of the Fock matrix
110!> \param qs_env ...
111!> \param ks_matrix ...
112!> \param matrix_p ...
113!> \param energy ...
114!> \param calculate_forces ...
115!> \param store_int_env ...
116!> \author JGH
117! **************************************************************************************************
118 SUBROUTINE build_fock_matrix_coulomb(qs_env, ks_matrix, matrix_p, energy, calculate_forces, &
119 store_int_env)
120
121 TYPE(qs_environment_type), POINTER :: qs_env
122 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ks_matrix, matrix_p
123 TYPE(qs_energy_type), POINTER :: energy
124 LOGICAL, INTENT(in) :: calculate_forces
125 TYPE(semi_empirical_si_type), POINTER :: store_int_env
126
127 CHARACTER(len=*), PARAMETER :: routinen = 'build_fock_matrix_coulomb'
128
129 INTEGER :: atom_a, atom_b, handle, iatom, ikind, inode, ispin, itype, jatom, jkind, &
130 natorb_a, natorb_a2, natorb_b, natorb_b2, nkind, nspins
131 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, se_natorb
132 LOGICAL :: anag, atener, check, defined, found, &
133 switch, use_virial
134 LOGICAL, ALLOCATABLE, DIMENSION(:) :: se_defined
135 REAL(kind=dp) :: delta, dr1, ecore2, ecores
136 REAL(kind=dp), DIMENSION(2) :: ecab
137 REAL(kind=dp), DIMENSION(2025) :: pa_a, pa_b, pb_a, pb_b
138 REAL(kind=dp), DIMENSION(3) :: force_ab, rij
139 REAL(kind=dp), DIMENSION(45, 45) :: p_block_tot_a, p_block_tot_b
140 REAL(kind=dp), DIMENSION(:, :), POINTER :: ksa_block_a, ksa_block_b, ksb_block_a, &
141 ksb_block_b, pa_block_a, pa_block_b, &
142 pb_block_a, pb_block_b
143 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
144 TYPE(atprop_type), POINTER :: atprop
145 TYPE(cell_type), POINTER :: cell
146 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: diagmat_ks, diagmat_p
147 TYPE(dft_control_type), POINTER :: dft_control
148 TYPE(ewald_environment_type), POINTER :: ewald_env
149 TYPE(ewald_pw_type), POINTER :: ewald_pw
150 TYPE(mp_para_env_type), POINTER :: para_env
152 DIMENSION(:), POINTER :: nl_iterator
153 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
154 POINTER :: sab_se
155 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
156 TYPE(qs_force_type), DIMENSION(:), POINTER :: force
157 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
158 TYPE(se_int_control_type) :: se_int_control
159 TYPE(se_taper_type), POINTER :: se_taper
160 TYPE(semi_empirical_control_type), POINTER :: se_control
161 TYPE(semi_empirical_p_type), DIMENSION(:), POINTER :: se_kind_list
162 TYPE(semi_empirical_type), POINTER :: se_kind_a, se_kind_b
163 TYPE(virial_type), POINTER :: virial
164
165 CALL timeset(routinen, handle)
166
167 NULLIFY (dft_control, cell, force, particle_set, diagmat_ks, diagmat_p, &
168 se_control, se_taper, virial, atprop)
169
170 CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, cell=cell, se_taper=se_taper, &
171 para_env=para_env, sab_se=sab_se, atomic_kind_set=atomic_kind_set, atprop=atprop, &
172 qs_kind_set=qs_kind_set, particle_set=particle_set, virial=virial)
173
174 ! Parameters
175 CALL initialize_se_taper(se_taper, coulomb=.true.)
176 se_control => dft_control%qs_control%se_control
177 anag = se_control%analytical_gradients
178 use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
179 atener = atprop%energy
180
181 CALL setup_se_int_control_type(se_int_control, do_ewald_r3=se_control%do_ewald_r3, &
182 do_ewald_gks=se_control%do_ewald_gks, integral_screening=se_control%integral_screening, &
183 shortrange=(se_control%do_ewald .OR. se_control%do_ewald_gks), &
184 max_multipole=se_control%max_multipole, pc_coulomb_int=.false.)
185 IF (se_control%do_ewald_gks) THEN
186 CALL get_qs_env(qs_env=qs_env, ewald_env=ewald_env, ewald_pw=ewald_pw)
187 CALL ewald_env_get(ewald_env, alpha=se_int_control%ewald_gks%alpha)
188 CALL ewald_pw_get(ewald_pw, pw_big_pool=se_int_control%ewald_gks%pw_pool, &
189 dg=se_int_control%ewald_gks%dg)
190 END IF
191
192 nspins = dft_control%nspins
193 cpassert(ASSOCIATED(matrix_p))
194 cpassert(SIZE(ks_matrix) > 0)
195
196 nkind = SIZE(atomic_kind_set)
197 IF (calculate_forces) THEN
198 CALL get_qs_env(qs_env=qs_env, force=force)
199 delta = se_control%delta
200 CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, atom_of_kind=atom_of_kind)
201 END IF
202
203 CALL dbcsr_allocate_matrix_set(diagmat_ks, nspins)
204 CALL dbcsr_allocate_matrix_set(diagmat_p, nspins)
205
206 DO ispin = 1, nspins
207 ! Allocate diagonal block matrices
208 ALLOCATE (diagmat_p(ispin)%matrix, diagmat_ks(ispin)%matrix) !sm->dbcsr
209 CALL dbcsr_get_block_diag(matrix_p(ispin)%matrix, diagmat_p(ispin)%matrix)
210 CALL dbcsr_get_block_diag(ks_matrix(ispin)%matrix, diagmat_ks(ispin)%matrix)
211 CALL dbcsr_set(diagmat_ks(ispin)%matrix, 0.0_dp)
212 CALL dbcsr_replicate_all(diagmat_p(ispin)%matrix)
213 CALL dbcsr_replicate_all(diagmat_ks(ispin)%matrix)
214 END DO
215
216 ecore2 = 0.0_dp
217 itype = get_se_type(dft_control%qs_control%method_id)
218 ALLOCATE (se_defined(nkind), se_kind_list(nkind), se_natorb(nkind))
219 DO ikind = 1, nkind
220 CALL get_qs_kind(qs_kind_set(ikind), se_parameter=se_kind_a)
221 se_kind_list(ikind)%se_param => se_kind_a
222 CALL get_se_param(se_kind_a, defined=defined, natorb=natorb_a)
223 se_defined(ikind) = (defined .AND. natorb_a >= 1)
224 se_natorb(ikind) = natorb_a
225 END DO
226
227 CALL neighbor_list_iterator_create(nl_iterator, sab_se)
228 DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
229 CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, iatom=iatom, jatom=jatom, inode=inode, r=rij)
230 IF (.NOT. se_defined(ikind)) cycle
231 IF (.NOT. se_defined(jkind)) cycle
232 se_kind_a => se_kind_list(ikind)%se_param
233 se_kind_b => se_kind_list(jkind)%se_param
234 natorb_a = se_natorb(ikind)
235 natorb_b = se_natorb(jkind)
236 natorb_a2 = natorb_a**2
237 natorb_b2 = natorb_b**2
238
239 IF (inode == 1) THEN
240 CALL dbcsr_get_block_p(matrix=diagmat_p(1)%matrix, &
241 row=iatom, col=iatom, block=pa_block_a, found=found)
242 cpassert(ASSOCIATED(pa_block_a))
243 check = (SIZE(pa_block_a, 1) == natorb_a) .AND. (SIZE(pa_block_a, 2) == natorb_a)
244 cpassert(check)
245 CALL dbcsr_get_block_p(matrix=diagmat_ks(1)%matrix, &
246 row=iatom, col=iatom, block=ksa_block_a, found=found)
247 cpassert(ASSOCIATED(ksa_block_a))
248 p_block_tot_a(1:natorb_a, 1:natorb_a) = 2.0_dp*pa_block_a
249 pa_a(1:natorb_a2) = reshape(pa_block_a, (/natorb_a2/))
250 IF (nspins == 2) THEN
251 CALL dbcsr_get_block_p(matrix=diagmat_p(2)%matrix, &
252 row=iatom, col=iatom, block=pa_block_b, found=found)
253 cpassert(ASSOCIATED(pa_block_b))
254 check = (SIZE(pa_block_b, 1) == natorb_a) .AND. (SIZE(pa_block_b, 2) == natorb_a)
255 cpassert(check)
256 CALL dbcsr_get_block_p(matrix=diagmat_ks(2)%matrix, &
257 row=iatom, col=iatom, block=ksa_block_b, found=found)
258 cpassert(ASSOCIATED(ksa_block_b))
259 p_block_tot_a(1:natorb_a, 1:natorb_a) = pa_block_a + pa_block_b
260 pa_b(1:natorb_a2) = reshape(pa_block_b, (/natorb_a2/))
261 END IF
262
263 END IF
264
265 dr1 = dot_product(rij, rij)
266 IF (dr1 > rij_threshold) THEN
267 ! Determine the order of the atoms, and in case switch them..
268 IF (iatom <= jatom) THEN
269 switch = .false.
270 ELSE
271 switch = .true.
272 END IF
273 ! Retrieve blocks for KS and P
274 CALL dbcsr_get_block_p(matrix=diagmat_p(1)%matrix, &
275 row=jatom, col=jatom, block=pb_block_a, found=found)
276 cpassert(ASSOCIATED(pb_block_a))
277 check = (SIZE(pb_block_a, 1) == natorb_b) .AND. (SIZE(pb_block_a, 2) == natorb_b)
278 cpassert(check)
279 CALL dbcsr_get_block_p(matrix=diagmat_ks(1)%matrix, &
280 row=jatom, col=jatom, block=ksb_block_a, found=found)
281 cpassert(ASSOCIATED(ksb_block_a))
282 p_block_tot_b(1:natorb_b, 1:natorb_b) = 2.0_dp*pb_block_a
283 pb_a(1:natorb_b2) = reshape(pb_block_a, (/natorb_b2/))
284 ! Handle more than one configuration
285 IF (nspins == 2) THEN
286 CALL dbcsr_get_block_p(matrix=diagmat_p(2)%matrix, &
287 row=jatom, col=jatom, block=pb_block_b, found=found)
288 cpassert(ASSOCIATED(pb_block_b))
289 check = (SIZE(pb_block_b, 1) == natorb_b) .AND. (SIZE(pb_block_b, 2) == natorb_b)
290 cpassert(check)
291 CALL dbcsr_get_block_p(matrix=diagmat_ks(2)%matrix, &
292 row=jatom, col=jatom, block=ksb_block_b, found=found)
293 cpassert(ASSOCIATED(ksb_block_b))
294 check = (SIZE(pb_block_a, 1) == SIZE(pb_block_b, 1)) .AND. (SIZE(pb_block_a, 2) == SIZE(pb_block_b, 2))
295 cpassert(check)
296 p_block_tot_b(1:natorb_b, 1:natorb_b) = pb_block_a + pb_block_b
297 pb_b(1:natorb_b2) = reshape(pb_block_b, (/natorb_b2/))
298 END IF
299
300 SELECT CASE (dft_control%qs_control%method_id)
303
304 ! Two-centers One-electron terms
305 IF (nspins == 1) THEN
306 ecab = 0._dp
307 CALL fock2_1el(se_kind_a, se_kind_b, rij, ksa_block_a, ksb_block_a, &
308 pa_a, pb_a, ecore=ecab, itype=itype, anag=anag, se_int_control=se_int_control, &
309 se_taper=se_taper, store_int_env=store_int_env)
310 ecore2 = ecore2 + ecab(1) + ecab(2)
311 ELSE IF (nspins == 2) THEN
312 ecab = 0._dp
313 CALL fock2_1el(se_kind_a, se_kind_b, rij, ksa_block_a, ksb_block_a, &
314 pa_block_a, pb_block_a, ecore=ecab, itype=itype, anag=anag, &
315 se_int_control=se_int_control, se_taper=se_taper, store_int_env=store_int_env)
316 CALL fock2_1el(se_kind_a, se_kind_b, rij, ksa_block_b, ksb_block_b, &
317 pa_b, pb_b, ecore=ecab, itype=itype, anag=anag, se_int_control=se_int_control, &
318 se_taper=se_taper, store_int_env=store_int_env)
319 ecore2 = ecore2 + ecab(1) + ecab(2)
320 END IF
321 IF (atener) THEN
322 atprop%atecoul(iatom) = atprop%atecoul(iatom) + ecab(1)
323 atprop%atecoul(jatom) = atprop%atecoul(jatom) + ecab(2)
324 END IF
325 ! Coulomb Terms
326 IF (nspins == 1) THEN
327 CALL fock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, ksa_block_a, p_block_tot_b, &
328 ksb_block_a, factor=0.5_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
329 store_int_env=store_int_env)
330 ELSE IF (nspins == 2) THEN
331 CALL fock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, ksa_block_a, p_block_tot_b, &
332 ksb_block_a, factor=1.0_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
333 store_int_env=store_int_env)
334
335 CALL fock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, ksa_block_b, p_block_tot_b, &
336 ksb_block_b, factor=1.0_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
337 store_int_env=store_int_env)
338 END IF
339
340 IF (calculate_forces) THEN
341 atom_a = atom_of_kind(iatom)
342 atom_b = atom_of_kind(jatom)
343
344 ! Derivatives of the Two-centre One-electron terms
345 force_ab = 0.0_dp
346 IF (nspins == 1) THEN
347 CALL dfock2_1el(se_kind_a, se_kind_b, rij, pa_a, pb_a, itype=itype, anag=anag, &
348 se_int_control=se_int_control, se_taper=se_taper, force=force_ab, &
349 delta=delta)
350 ELSE IF (nspins == 2) THEN
351 CALL dfock2_1el(se_kind_a, se_kind_b, rij, pa_block_a, pb_block_a, itype=itype, anag=anag, &
352 se_int_control=se_int_control, se_taper=se_taper, force=force_ab, delta=delta)
353 CALL dfock2_1el(se_kind_a, se_kind_b, rij, pa_b, pb_b, itype=itype, anag=anag, &
354 se_int_control=se_int_control, se_taper=se_taper, force=force_ab, delta=delta)
355 END IF
356 IF (use_virial) THEN
357 CALL virial_pair_force(virial%pv_virial, -1.0_dp, force_ab, rij)
358 END IF
359
360 ! Sum up force components
361 force(ikind)%all_potential(1, atom_a) = force(ikind)%all_potential(1, atom_a) - force_ab(1)
362 force(jkind)%all_potential(1, atom_b) = force(jkind)%all_potential(1, atom_b) + force_ab(1)
363
364 force(ikind)%all_potential(2, atom_a) = force(ikind)%all_potential(2, atom_a) - force_ab(2)
365 force(jkind)%all_potential(2, atom_b) = force(jkind)%all_potential(2, atom_b) + force_ab(2)
366
367 force(ikind)%all_potential(3, atom_a) = force(ikind)%all_potential(3, atom_a) - force_ab(3)
368 force(jkind)%all_potential(3, atom_b) = force(jkind)%all_potential(3, atom_b) + force_ab(3)
369
370 ! Derivatives of the Coulomb Terms
371 force_ab = 0._dp
372 IF (nspins == 1) THEN
373 CALL dfock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, p_block_tot_b, factor=0.25_dp, &
374 anag=anag, se_int_control=se_int_control, se_taper=se_taper, force=force_ab, delta=delta)
375 ELSE IF (nspins == 2) THEN
376 CALL dfock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, p_block_tot_b, factor=0.50_dp, &
377 anag=anag, se_int_control=se_int_control, se_taper=se_taper, force=force_ab, delta=delta)
378
379 CALL dfock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, p_block_tot_b, factor=0.50_dp, &
380 anag=anag, se_int_control=se_int_control, se_taper=se_taper, force=force_ab, delta=delta)
381 END IF
382 IF (switch) THEN
383 force_ab(1) = -force_ab(1)
384 force_ab(2) = -force_ab(2)
385 force_ab(3) = -force_ab(3)
386 END IF
387 IF (use_virial) THEN
388 CALL virial_pair_force(virial%pv_virial, -1.0_dp, force_ab, rij)
389 END IF
390 ! Sum up force components
391 force(ikind)%rho_elec(1, atom_a) = force(ikind)%rho_elec(1, atom_a) - force_ab(1)
392 force(jkind)%rho_elec(1, atom_b) = force(jkind)%rho_elec(1, atom_b) + force_ab(1)
393
394 force(ikind)%rho_elec(2, atom_a) = force(ikind)%rho_elec(2, atom_a) - force_ab(2)
395 force(jkind)%rho_elec(2, atom_b) = force(jkind)%rho_elec(2, atom_b) + force_ab(2)
396
397 force(ikind)%rho_elec(3, atom_a) = force(ikind)%rho_elec(3, atom_a) - force_ab(3)
398 force(jkind)%rho_elec(3, atom_b) = force(jkind)%rho_elec(3, atom_b) + force_ab(3)
399 END IF
400 CASE DEFAULT
401 cpabort("")
402 END SELECT
403 ELSE
404 IF (se_int_control%do_ewald_gks) THEN
405 cpassert(iatom == jatom)
406 ! Two-centers One-electron terms
407 ecores = 0._dp
408 IF (nspins == 1) THEN
409 CALL fock2_1el_ew(se_kind_a, rij, ksa_block_a, pa_a, &
410 ecore=ecores, itype=itype, anag=anag, se_int_control=se_int_control, &
411 se_taper=se_taper, store_int_env=store_int_env)
412 ELSE IF (nspins == 2) THEN
413 CALL fock2_1el_ew(se_kind_a, rij, ksa_block_a, pa_block_a, &
414 ecore=ecores, itype=itype, anag=anag, se_int_control=se_int_control, &
415 se_taper=se_taper, store_int_env=store_int_env)
416 CALL fock2_1el_ew(se_kind_a, rij, ksa_block_b, pa_b, &
417 ecore=ecores, itype=itype, anag=anag, se_int_control=se_int_control, &
418 se_taper=se_taper, store_int_env=store_int_env)
419 END IF
420 ecore2 = ecore2 + ecores
421 IF (atener) THEN
422 atprop%atecoul(iatom) = atprop%atecoul(iatom) + ecores
423 END IF
424 ! Coulomb Terms
425 IF (nspins == 1) THEN
426 CALL fock2c_ew(se_kind_a, rij, p_block_tot_a, ksa_block_a, &
427 factor=0.5_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
428 store_int_env=store_int_env)
429 ELSE IF (nspins == 2) THEN
430 CALL fock2c_ew(se_kind_a, rij, p_block_tot_a, ksa_block_a, &
431 factor=1.0_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
432 store_int_env=store_int_env)
433 CALL fock2c_ew(se_kind_a, rij, p_block_tot_a, ksa_block_b, &
434 factor=1.0_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
435 store_int_env=store_int_env)
436 END IF
437 END IF
438 END IF
439 END DO
440 CALL neighbor_list_iterator_release(nl_iterator)
441
442 DEALLOCATE (se_kind_list, se_defined, se_natorb)
443
444 DO ispin = 1, nspins
445 CALL dbcsr_sum_replicated(diagmat_ks(ispin)%matrix)
446 CALL dbcsr_distribute(diagmat_ks(ispin)%matrix)
447 CALL dbcsr_add(ks_matrix(ispin)%matrix, diagmat_ks(ispin)%matrix, &
448 1.0_dp, 1.0_dp)
449 END DO
450 CALL dbcsr_deallocate_matrix_set(diagmat_p)
451 CALL dbcsr_deallocate_matrix_set(diagmat_ks)
452
453 ! Two-centers one-electron terms
454 CALL para_env%sum(ecore2)
455 energy%hartree = ecore2 - energy%core
456! WRITE ( *, * ) 'IN SE_F_COUL', ecore2, energy%core
457
458 CALL finalize_se_taper(se_taper)
459
460 CALL timestop(handle)
461 END SUBROUTINE build_fock_matrix_coulomb
462
463! **************************************************************************************************
464!> \brief Long-Range part for SE Coulomb interactions
465!> \param qs_env ...
466!> \param ks_matrix ...
467!> \param matrix_p ...
468!> \param energy ...
469!> \param calculate_forces ...
470!> \param store_int_env ...
471!> \date 08.2008 [created]
472!> \author Teodoro Laino [tlaino] - University of Zurich
473! **************************************************************************************************
474 SUBROUTINE build_fock_matrix_coulomb_lr(qs_env, ks_matrix, matrix_p, energy, &
475 calculate_forces, store_int_env)
476
477 TYPE(qs_environment_type), POINTER :: qs_env
478 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ks_matrix, matrix_p
479 TYPE(qs_energy_type), POINTER :: energy
480 LOGICAL, INTENT(in) :: calculate_forces
481 TYPE(semi_empirical_si_type), POINTER :: store_int_env
482
483 CHARACTER(len=*), PARAMETER :: routinen = 'build_fock_matrix_coulomb_lr'
484
485 INTEGER :: atom_a, ewald_type, forces_g_size, handle, iatom, ikind, ilist, indi, indj, &
486 ispin, itype, iw, jint, natoms, natorb_a, nkind, nlocal_particles, node, nparticle_local, &
487 nspins, size_1c_int
488 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind
489 LOGICAL :: anag, atener, defined, found, use_virial
490 LOGICAL, DIMENSION(3) :: task
491 REAL(kind=dp) :: e_neut, e_self, energy_glob, &
492 energy_local, enuc, fac, tmp
493 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: forces_g, forces_r
494 REAL(kind=dp), DIMENSION(3) :: force_a
495 REAL(kind=dp), DIMENSION(3, 3) :: pv_glob, pv_local, qcart
496 REAL(kind=dp), DIMENSION(5) :: qsph
497 REAL(kind=dp), DIMENSION(:, :), POINTER :: ksa_block_a, pa_block_a
498 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
499 TYPE(atprop_type), POINTER :: atprop
500 TYPE(cell_type), POINTER :: cell
501 TYPE(cp_logger_type), POINTER :: logger
502 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: diagmat_ks, diagmat_p
503 TYPE(dft_control_type), POINTER :: dft_control
504 TYPE(distribution_1d_type), POINTER :: local_particles
505 TYPE(ewald_environment_type), POINTER :: ewald_env
506 TYPE(ewald_pw_type), POINTER :: ewald_pw
507 TYPE(fist_nonbond_env_type), POINTER :: se_nonbond_env
508 TYPE(mp_para_env_type), POINTER :: para_env
509 TYPE(nddo_mpole_type), POINTER :: se_nddo_mpole
510 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
511 TYPE(qs_force_type), DIMENSION(:), POINTER :: force
512 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
513 TYPE(section_vals_type), POINTER :: se_section
514 TYPE(semi_empirical_control_type), POINTER :: se_control
515 TYPE(semi_empirical_mpole_type), POINTER :: mpole
516 TYPE(semi_empirical_type), POINTER :: se_kind_a
517 TYPE(virial_type), POINTER :: virial
518
519 CALL timeset(routinen, handle)
520
521 NULLIFY (dft_control, cell, force, particle_set, diagmat_ks, diagmat_p, local_particles, &
522 se_control, ewald_env, ewald_pw, se_nddo_mpole, se_nonbond_env, se_section, mpole, &
523 logger, virial, atprop)
524
525 logger => cp_get_default_logger()
526 CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, cell=cell, para_env=para_env, &
527 atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set, particle_set=particle_set, &
528 ewald_env=ewald_env, &
529 local_particles=local_particles, ewald_pw=ewald_pw, se_nddo_mpole=se_nddo_mpole, &
530 se_nonbond_env=se_nonbond_env, virial=virial, atprop=atprop)
531
532 nlocal_particles = sum(local_particles%n_el(:))
533 natoms = SIZE(particle_set)
534 CALL ewald_env_get(ewald_env, ewald_type=ewald_type)
535 SELECT CASE (ewald_type)
536 CASE (do_ewald_ewald)
537 forces_g_size = nlocal_particles
538 CASE DEFAULT
539 cpabort("Periodic SE implemented only for standard EWALD sums.")
540 END SELECT
541
542 ! Parameters
543 se_section => section_vals_get_subs_vals(qs_env%input, "DFT%QS%SE")
544 se_control => dft_control%qs_control%se_control
545 anag = se_control%analytical_gradients
546 use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer) .AND. calculate_forces
547 atener = atprop%energy
548
549 nspins = dft_control%nspins
550 cpassert(ASSOCIATED(matrix_p))
551 cpassert(SIZE(ks_matrix) > 0)
552
553 CALL dbcsr_allocate_matrix_set(diagmat_ks, nspins)
554 CALL dbcsr_allocate_matrix_set(diagmat_p, nspins)
555
556 nkind = SIZE(atomic_kind_set)
557 DO ispin = 1, nspins
558 ! Allocate diagonal block matrices
559 ALLOCATE (diagmat_p(ispin)%matrix, diagmat_ks(ispin)%matrix) !sm->dbcsr
560 CALL dbcsr_get_block_diag(matrix_p(ispin)%matrix, diagmat_p(ispin)%matrix)
561 CALL dbcsr_get_block_diag(ks_matrix(ispin)%matrix, diagmat_ks(ispin)%matrix)
562 CALL dbcsr_set(diagmat_ks(ispin)%matrix, 0.0_dp)
563 CALL dbcsr_replicate_all(diagmat_p(ispin)%matrix)
564 CALL dbcsr_replicate_all(diagmat_ks(ispin)%matrix)
565 END DO
566
567 ! Check for implemented SE methods
568 SELECT CASE (dft_control%qs_control%method_id)
571 itype = get_se_type(dft_control%qs_control%method_id)
572 CASE DEFAULT
573 cpabort("")
574 END SELECT
575
576 ! Zero arrays and possibly build neighbor lists
577 energy_local = 0.0_dp
578 energy_glob = 0.0_dp
579 e_neut = 0.0_dp
580 e_self = 0.0_dp
581 task = .false.
582 SELECT CASE (se_control%max_multipole)
583 CASE (do_multipole_none)
584 ! Do Nothing
586 task(1) = .true.
588 task = .true.
589 task(3) = .false.
591 task = .true.
592 CASE DEFAULT
593 cpabort("")
594 END SELECT
595
596 ! Build-up neighbor lists for real-space part of Ewald multipoles
597 CALL list_control(atomic_kind_set, particle_set, local_particles, &
598 cell, se_nonbond_env, para_env, se_section)
599
600 enuc = 0.0_dp
601 energy%core_overlap = 0.0_dp
602 se_nddo_mpole%charge = 0.0_dp
603 se_nddo_mpole%dipole = 0.0_dp
604 se_nddo_mpole%quadrupole = 0.0_dp
605
606 DO ispin = 1, nspins
607 ! Compute the NDDO mpole expansion
608 DO ikind = 1, nkind
609 CALL get_qs_kind(qs_kind_set(ikind), se_parameter=se_kind_a)
610 CALL get_se_param(se_kind_a, defined=defined, natorb=natorb_a)
611
612 IF (.NOT. defined .OR. natorb_a < 1) cycle
613
614 nparticle_local = local_particles%n_el(ikind)
615 DO ilist = 1, nparticle_local
616 iatom = local_particles%list(ikind)%array(ilist)
617 CALL dbcsr_get_block_p(matrix=diagmat_p(ispin)%matrix, &
618 row=iatom, col=iatom, block=pa_block_a, found=found)
619 cpassert(ASSOCIATED(pa_block_a))
620 ! Nuclei
621 IF (task(1) .AND. ispin == 1) se_nddo_mpole%charge(iatom) = se_kind_a%zeff
622 ! Electrons
623 size_1c_int = SIZE(se_kind_a%w_mpole)
624 DO jint = 1, size_1c_int
625 mpole => se_kind_a%w_mpole(jint)%mpole
626 indi = se_orbital_pointer(mpole%indi)
627 indj = se_orbital_pointer(mpole%indj)
628 fac = 1.0_dp
629 IF (indi /= indj) fac = 2.0_dp
630
631 ! Charge
632 IF (mpole%task(1) .AND. task(1)) THEN
633 se_nddo_mpole%charge(iatom) = se_nddo_mpole%charge(iatom) + &
634 fac*pa_block_a(indi, indj)*mpole%c
635 END IF
636
637 ! Dipole
638 IF (mpole%task(2) .AND. task(2)) THEN
639 se_nddo_mpole%dipole(:, iatom) = se_nddo_mpole%dipole(:, iatom) + &
640 fac*pa_block_a(indi, indj)*mpole%d(:)
641 END IF
642
643 ! Quadrupole
644 IF (mpole%task(3) .AND. task(3)) THEN
645 qsph = fac*mpole%qs*pa_block_a(indi, indj)
646 CALL quadrupole_sph_to_cart(qcart, qsph)
647 se_nddo_mpole%quadrupole(:, :, iatom) = se_nddo_mpole%quadrupole(:, :, iatom) + &
648 qcart
649 END IF
650 END DO
651 ! Print some info about charge, dipole and quadrupole (debug purpose only)
652 IF (debug_this_module) THEN
653 WRITE (*, '(I5,F12.6,5X,3F12.6,5X,9F12.6)') iatom, se_nddo_mpole%charge(iatom), &
654 se_nddo_mpole%dipole(:, iatom), se_nddo_mpole%quadrupole(:, :, iatom)
655 END IF
656 END DO
657 END DO
658 END DO
659 CALL para_env%sum(se_nddo_mpole%charge)
660 CALL para_env%sum(se_nddo_mpole%dipole)
661 CALL para_env%sum(se_nddo_mpole%quadrupole)
662
663 ! Initialize for virial
664 IF (use_virial) THEN
665 pv_glob = 0.0_dp
666 pv_local = 0.0_dp
667 END IF
668
669 ! Ewald Multipoles Sum
670 iw = cp_print_key_unit_nr(logger, se_section, "PRINT%EWALD_INFO", extension=".seLog")
671 IF (calculate_forces) THEN
672 CALL get_qs_env(qs_env=qs_env, force=force)
673 CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, atom_of_kind=atom_of_kind)
674
675 ! Allocate and zeroing arrays
676 ALLOCATE (forces_g(3, forces_g_size))
677 ALLOCATE (forces_r(3, natoms))
678 forces_g = 0.0_dp
679 forces_r = 0.0_dp
681 ewald_env, ewald_pw, se_nonbond_env, cell, &
682 particle_set, local_particles, energy_local, energy_glob, e_neut, e_self, task, &
683 do_correction_bonded=.false., do_forces=.true., do_stress=use_virial, do_efield=.true., &
684 charges=se_nddo_mpole%charge, dipoles=se_nddo_mpole%dipole, quadrupoles=se_nddo_mpole%quadrupole, &
685 forces_local=forces_g, forces_glob=forces_r, pv_glob=pv_glob, pv_local=pv_local, &
686 efield0=se_nddo_mpole%efield0, efield1=se_nddo_mpole%efield1, efield2=se_nddo_mpole%efield2, iw=iw, &
687 do_debug=.true.)
688 ! Only SR force have to be summed up.. the one in g-space are already fully local..
689 CALL para_env%sum(forces_r)
690 ELSE
692 ewald_env, ewald_pw, se_nonbond_env, cell, &
693 particle_set, local_particles, energy_local, energy_glob, e_neut, e_self, task, &
694 do_correction_bonded=.false., do_forces=.false., do_stress=.false., do_efield=.true., &
695 charges=se_nddo_mpole%charge, dipoles=se_nddo_mpole%dipole, quadrupoles=se_nddo_mpole%quadrupole, &
696 efield0=se_nddo_mpole%efield0, efield1=se_nddo_mpole%efield1, efield2=se_nddo_mpole%efield2, &
697 iw=iw, do_debug=.true.)
698 END IF
699 CALL cp_print_key_finished_output(iw, logger, se_section, "PRINT%EWALD_INFO")
700
701 ! Apply correction only when the Integral Scheme is different from Slater
702 IF ((se_control%integral_screening /= do_se_is_slater) .AND. (.NOT. debug_this_module)) THEN
703 CALL build_fock_matrix_coul_lrc(qs_env, ks_matrix, matrix_p, energy, calculate_forces, &
704 store_int_env, se_nddo_mpole, task, diagmat_p, diagmat_ks, virial, &
705 pv_glob)
706 END IF
707
708 ! Virial for the long-range part and correction
709 IF (use_virial) THEN
710 ! Sum up contribution of pv_glob on each thread and keep only one copy of pv_local
711 virial%pv_virial = virial%pv_virial + pv_glob
712 IF (para_env%is_source()) THEN
713 virial%pv_virial = virial%pv_virial + pv_local
714 END IF
715 END IF
716
717 ! Debug Statements
718 IF (debug_this_module) THEN
719 CALL para_env%sum(energy_glob)
720 WRITE (*, *) "TOTAL ENERGY AFTER EWALD:", energy_local + energy_glob + e_neut + e_self, &
721 energy_local, energy_glob, e_neut, e_self
722 END IF
723
724 ! Modify the KS matrix and possibly compute derivatives
725 node = 0
726 DO ikind = 1, nkind
727 CALL get_qs_kind(qs_kind_set(ikind), se_parameter=se_kind_a)
728 CALL get_se_param(se_kind_a, defined=defined, natorb=natorb_a)
729
730 IF (.NOT. defined .OR. natorb_a < 1) cycle
731
732 nparticle_local = local_particles%n_el(ikind)
733 DO ilist = 1, nparticle_local
734 node = node + 1
735 iatom = local_particles%list(ikind)%array(ilist)
736 DO ispin = 1, nspins
737 CALL dbcsr_get_block_p(matrix=diagmat_ks(ispin)%matrix, &
738 row=iatom, col=iatom, block=ksa_block_a, found=found)
739 cpassert(ASSOCIATED(ksa_block_a))
740
741 ! Modify Hamiltonian Matrix accordingly potential, field and electric field gradient
742 size_1c_int = SIZE(se_kind_a%w_mpole)
743 DO jint = 1, size_1c_int
744 tmp = 0.0_dp
745 mpole => se_kind_a%w_mpole(jint)%mpole
746 indi = se_orbital_pointer(mpole%indi)
747 indj = se_orbital_pointer(mpole%indj)
748
749 ! Charge
750 IF (mpole%task(1) .AND. task(1)) THEN
751 tmp = tmp + mpole%c*se_nddo_mpole%efield0(iatom)
752 END IF
753
754 ! Dipole
755 IF (mpole%task(2) .AND. task(2)) THEN
756 tmp = tmp - dot_product(mpole%d, se_nddo_mpole%efield1(:, iatom))
757 END IF
758
759 ! Quadrupole
760 IF (mpole%task(3) .AND. task(3)) THEN
761 tmp = tmp - (1.0_dp/3.0_dp)*sum(mpole%qc*reshape(se_nddo_mpole%efield2(:, iatom), (/3, 3/)))
762 END IF
763
764 ksa_block_a(indi, indj) = ksa_block_a(indi, indj) + tmp
765 ksa_block_a(indj, indi) = ksa_block_a(indi, indj)
766 END DO
767 END DO
768
769 ! Nuclear term and forces
770 IF (task(1)) enuc = enuc + se_kind_a%zeff*se_nddo_mpole%efield0(iatom)
771 IF (atener) THEN
772 atprop%atecoul(iatom) = atprop%atecoul(iatom) + &
773 0.5_dp*se_kind_a%zeff*se_nddo_mpole%efield0(iatom)
774 END IF
775 IF (calculate_forces) THEN
776 atom_a = atom_of_kind(iatom)
777 force_a = forces_r(1:3, iatom) + forces_g(1:3, node)
778 ! Derivatives of the periodic Coulomb Terms
779 force(ikind)%all_potential(:, atom_a) = force(ikind)%all_potential(:, atom_a) - force_a(:)
780 END IF
781 END DO
782 END DO
783 ! Sum nuclear energy contribution
784 CALL para_env%sum(enuc)
785 energy%core_overlap = energy%core_overlap + energy%core_overlap0 + 0.5_dp*enuc
786
787 ! Debug Statements
788 IF (debug_this_module) THEN
789 WRITE (*, *) "ENUC: ", enuc*0.5_dp
790 END IF
791
792 DO ispin = 1, nspins
793 CALL dbcsr_sum_replicated(diagmat_ks(ispin)%matrix)
794 CALL dbcsr_distribute(diagmat_ks(ispin)%matrix)
795 CALL dbcsr_add(ks_matrix(ispin)%matrix, diagmat_ks(ispin)%matrix, &
796 1.0_dp, 1.0_dp)
797 END DO
798 CALL dbcsr_deallocate_matrix_set(diagmat_p)
799 CALL dbcsr_deallocate_matrix_set(diagmat_ks)
800
801 ! Set the Fock matrix contribution to SCP
802 IF (calculate_forces) THEN
803 DEALLOCATE (forces_g)
804 DEALLOCATE (forces_r)
805 END IF
806
807 CALL timestop(handle)
808 END SUBROUTINE build_fock_matrix_coulomb_lr
809
810! **************************************************************************************************
811!> \brief When doing long-range SE calculation, this module computes the correction
812!> between the mismatch of point-like multipoles and multipoles represented
813!> with charges
814!> \param qs_env ...
815!> \param ks_matrix ...
816!> \param matrix_p ...
817!> \param energy ...
818!> \param calculate_forces ...
819!> \param store_int_env ...
820!> \param se_nddo_mpole ...
821!> \param task ...
822!> \param diagmat_p ...
823!> \param diagmat_ks ...
824!> \param virial ...
825!> \param pv_glob ...
826!> \author Teodoro Laino [tlaino] - 05.2009
827! **************************************************************************************************
828 SUBROUTINE build_fock_matrix_coul_lrc(qs_env, ks_matrix, matrix_p, energy, &
829 calculate_forces, store_int_env, se_nddo_mpole, task, diagmat_p, diagmat_ks, &
830 virial, pv_glob)
831
832 TYPE(qs_environment_type), POINTER :: qs_env
833 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ks_matrix, matrix_p
834 TYPE(qs_energy_type), POINTER :: energy
835 LOGICAL, INTENT(in) :: calculate_forces
836 TYPE(semi_empirical_si_type), POINTER :: store_int_env
837 TYPE(nddo_mpole_type), POINTER :: se_nddo_mpole
838 LOGICAL, DIMENSION(3), INTENT(IN) :: task
839 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: diagmat_p, diagmat_ks
840 TYPE(virial_type), POINTER :: virial
841 REAL(kind=dp), DIMENSION(3, 3), INTENT(INOUT) :: pv_glob
842
843 CHARACTER(len=*), PARAMETER :: routinen = 'build_fock_matrix_coul_lrc'
844
845 INTEGER :: atom_a, atom_b, handle, iatom, ikind, inode, itype, jatom, jkind, natorb_a, &
846 natorb_a2, natorb_b, natorb_b2, nkind, nspins, size1, size2
847 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, se_natorb
848 LOGICAL :: anag, atener, check, defined, found, &
849 switch, use_virial
850 LOGICAL, ALLOCATABLE, DIMENSION(:) :: se_defined
851 REAL(kind=dp) :: delta, dr1, ecore2, enuc, enuclear, &
852 ptens11, ptens12, ptens13, ptens21, &
853 ptens22, ptens23, ptens31, ptens32, &
854 ptens33
855 REAL(kind=dp), DIMENSION(2) :: ecab
856 REAL(kind=dp), DIMENSION(2025) :: pa_a, pa_b, pb_a, pb_b
857 REAL(kind=dp), DIMENSION(3) :: force_ab, force_ab0, rij
858 REAL(kind=dp), DIMENSION(45, 45) :: p_block_tot_a, p_block_tot_b
859 REAL(kind=dp), DIMENSION(:), POINTER :: efield0
860 REAL(kind=dp), DIMENSION(:, :), POINTER :: efield1, efield2, ksa_block_a, ksa_block_b, &
861 ksb_block_a, ksb_block_b, pa_block_a, pa_block_b, pb_block_a, pb_block_b
862 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
863 TYPE(atprop_type), POINTER :: atprop
864 TYPE(cell_type), POINTER :: cell
865 TYPE(dft_control_type), POINTER :: dft_control
866 TYPE(mp_para_env_type), POINTER :: para_env
868 DIMENSION(:), POINTER :: nl_iterator
869 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
870 POINTER :: sab_lrc
871 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
872 TYPE(qs_force_type), DIMENSION(:), POINTER :: force
873 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
874 TYPE(se_int_control_type) :: se_int_control
875 TYPE(se_taper_type), POINTER :: se_taper
876 TYPE(semi_empirical_control_type), POINTER :: se_control
877 TYPE(semi_empirical_p_type), DIMENSION(:), POINTER :: se_kind_list
878 TYPE(semi_empirical_type), POINTER :: se_kind_a, se_kind_b
879
880 CALL timeset(routinen, handle)
881 NULLIFY (dft_control, cell, force, particle_set, se_control, se_taper, &
882 efield0, efield1, efield2, atprop)
883
884 CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, cell=cell, se_taper=se_taper, &
885 para_env=para_env, sab_lrc=sab_lrc, atomic_kind_set=atomic_kind_set, &
886 qs_kind_set=qs_kind_set, particle_set=particle_set, atprop=atprop)
887
888 ! Parameters
889 CALL initialize_se_taper(se_taper, lr_corr=.true.)
890 se_control => dft_control%qs_control%se_control
891 anag = se_control%analytical_gradients
892 use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer) .AND. calculate_forces
893 atener = atprop%energy
894
895 CALL setup_se_int_control_type(se_int_control, do_ewald_r3=se_control%do_ewald_r3, &
896 do_ewald_gks=.false., integral_screening=se_control%integral_screening, &
897 shortrange=.false., max_multipole=se_control%max_multipole, &
898 pc_coulomb_int=.true.)
899
900 nspins = dft_control%nspins
901 cpassert(ASSOCIATED(matrix_p))
902 cpassert(SIZE(ks_matrix) > 0)
903 cpassert(ASSOCIATED(diagmat_p))
904 cpassert(ASSOCIATED(diagmat_ks))
905 mark_used(ks_matrix)
906 mark_used(matrix_p)
907
908 nkind = SIZE(atomic_kind_set)
909 IF (calculate_forces) THEN
910 CALL get_qs_env(qs_env=qs_env, force=force)
911 delta = se_control%delta
912 CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, atom_of_kind=atom_of_kind)
913 END IF
914
915 ! Allocate arrays for storing partial information on potential, field, field gradient
916 size1 = SIZE(se_nddo_mpole%efield0)
917 ALLOCATE (efield0(size1))
918 efield0 = 0.0_dp
919 size1 = SIZE(se_nddo_mpole%efield1, 1)
920 size2 = SIZE(se_nddo_mpole%efield1, 2)
921 ALLOCATE (efield1(size1, size2))
922 efield1 = 0.0_dp
923 size1 = SIZE(se_nddo_mpole%efield2, 1)
924 size2 = SIZE(se_nddo_mpole%efield2, 2)
925 ALLOCATE (efield2(size1, size2))
926 efield2 = 0.0_dp
927
928 ! Initialize if virial is requested
929 IF (use_virial) THEN
930 ptens11 = 0.0_dp; ptens12 = 0.0_dp; ptens13 = 0.0_dp
931 ptens21 = 0.0_dp; ptens22 = 0.0_dp; ptens23 = 0.0_dp
932 ptens31 = 0.0_dp; ptens32 = 0.0_dp; ptens33 = 0.0_dp
933 END IF
934
935 ! Start of the loop for the correction of the pair interactions
936 ecore2 = 0.0_dp
937 enuclear = 0.0_dp
938 itype = get_se_type(dft_control%qs_control%method_id)
939
940 ALLOCATE (se_defined(nkind), se_kind_list(nkind), se_natorb(nkind))
941 DO ikind = 1, nkind
942 CALL get_qs_kind(qs_kind_set(ikind), se_parameter=se_kind_a)
943 se_kind_list(ikind)%se_param => se_kind_a
944 CALL get_se_param(se_kind_a, defined=defined, natorb=natorb_a)
945 se_defined(ikind) = (defined .AND. natorb_a >= 1)
946 se_natorb(ikind) = natorb_a
947 END DO
948
949 CALL neighbor_list_iterator_create(nl_iterator, sab_lrc)
950 DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
951 CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, iatom=iatom, jatom=jatom, inode=inode, r=rij)
952 IF (.NOT. se_defined(ikind)) cycle
953 IF (.NOT. se_defined(jkind)) cycle
954 se_kind_a => se_kind_list(ikind)%se_param
955 se_kind_b => se_kind_list(jkind)%se_param
956 natorb_a = se_natorb(ikind)
957 natorb_b = se_natorb(jkind)
958 natorb_a2 = natorb_a**2
959 natorb_b2 = natorb_b**2
960
961 IF (inode == 1) THEN
962 CALL dbcsr_get_block_p(matrix=diagmat_p(1)%matrix, &
963 row=iatom, col=iatom, block=pa_block_a, found=found)
964 cpassert(ASSOCIATED(pa_block_a))
965 check = (SIZE(pa_block_a, 1) == natorb_a) .AND. (SIZE(pa_block_a, 2) == natorb_a)
966 cpassert(check)
967 CALL dbcsr_get_block_p(matrix=diagmat_ks(1)%matrix, &
968 row=iatom, col=iatom, block=ksa_block_a, found=found)
969 cpassert(ASSOCIATED(ksa_block_a))
970 p_block_tot_a(1:natorb_a, 1:natorb_a) = 2.0_dp*pa_block_a
971 pa_a(1:natorb_a2) = reshape(pa_block_a, (/natorb_a2/))
972 IF (nspins == 2) THEN
973 CALL dbcsr_get_block_p(matrix=diagmat_p(2)%matrix, &
974 row=iatom, col=iatom, block=pa_block_b, found=found)
975 cpassert(ASSOCIATED(pa_block_b))
976 check = (SIZE(pa_block_b, 1) == natorb_a) .AND. (SIZE(pa_block_b, 2) == natorb_a)
977 cpassert(check)
978 CALL dbcsr_get_block_p(matrix=diagmat_ks(2)%matrix, &
979 row=iatom, col=iatom, block=ksa_block_b, found=found)
980 cpassert(ASSOCIATED(ksa_block_b))
981 p_block_tot_a(1:natorb_a, 1:natorb_a) = pa_block_a + pa_block_b
982 pa_b(1:natorb_a2) = reshape(pa_block_b, (/natorb_a2/))
983 END IF
984
985 END IF
986
987 dr1 = dot_product(rij, rij)
988 IF (dr1 > rij_threshold) THEN
989 ! Determine the order of the atoms, and in case switch them..
990 IF (iatom <= jatom) THEN
991 switch = .false.
992 ELSE
993 switch = .true.
994 END IF
995
996 ! Point-like interaction corrections
997 CALL se_coulomb_ij_interaction(iatom, jatom, task, do_forces=calculate_forces, &
998 do_efield=.true., do_stress=use_virial, charges=se_nddo_mpole%charge, &
999 dipoles=se_nddo_mpole%dipole, quadrupoles=se_nddo_mpole%quadrupole, &
1000 force_ab=force_ab0, efield0=efield0, efield1=efield1, efield2=efield2, &
1001 rab2=dr1, rab=rij, ptens11=ptens11, ptens12=ptens12, ptens13=ptens13, &
1002 ptens21=ptens21, ptens22=ptens22, ptens23=ptens23, ptens31=ptens31, &
1003 ptens32=ptens32, ptens33=ptens33)
1004
1005 ! Retrieve blocks for KS and P
1006 CALL dbcsr_get_block_p(matrix=diagmat_p(1)%matrix, &
1007 row=jatom, col=jatom, block=pb_block_a, found=found)
1008 cpassert(ASSOCIATED(pb_block_a))
1009 check = (SIZE(pb_block_a, 1) == natorb_b) .AND. (SIZE(pb_block_a, 2) == natorb_b)
1010 cpassert(check)
1011 CALL dbcsr_get_block_p(matrix=diagmat_ks(1)%matrix, &
1012 row=jatom, col=jatom, block=ksb_block_a, found=found)
1013 cpassert(ASSOCIATED(ksb_block_a))
1014 p_block_tot_b(1:natorb_b, 1:natorb_b) = 2.0_dp*pb_block_a
1015 pb_a(1:natorb_b2) = reshape(pb_block_a, (/natorb_b2/))
1016 ! Handle more than one configuration
1017 IF (nspins == 2) THEN
1018 CALL dbcsr_get_block_p(matrix=diagmat_p(2)%matrix, &
1019 row=jatom, col=jatom, block=pb_block_b, found=found)
1020 cpassert(ASSOCIATED(pb_block_b))
1021 check = (SIZE(pb_block_b, 1) == natorb_b) .AND. (SIZE(pb_block_b, 2) == natorb_b)
1022 cpassert(check)
1023 CALL dbcsr_get_block_p(matrix=diagmat_ks(2)%matrix, &
1024 row=jatom, col=jatom, block=ksb_block_b, found=found)
1025 cpassert(ASSOCIATED(ksb_block_b))
1026 check = (SIZE(pb_block_a, 1) == SIZE(pb_block_b, 1)) .AND. (SIZE(pb_block_a, 2) == SIZE(pb_block_b, 2))
1027 cpassert(check)
1028 p_block_tot_b(1:natorb_b, 1:natorb_b) = pb_block_a + pb_block_b
1029 pb_b(1:natorb_b2) = reshape(pb_block_b, (/natorb_b2/))
1030 END IF
1031
1032 SELECT CASE (dft_control%qs_control%method_id)
1035 ! Evaluate nuclear contribution..
1036 CALL corecore_el(se_kind_a, se_kind_b, rij, enuc=enuc, itype=itype, anag=anag, &
1037 se_int_control=se_int_control, se_taper=se_taper)
1038 enuclear = enuclear + enuc
1039
1040 ! Two-centers One-electron terms
1041 IF (nspins == 1) THEN
1042 ecab = 0._dp
1043 CALL fock2_1el(se_kind_a, se_kind_b, rij, ksa_block_a, ksb_block_a, &
1044 pa_a, pb_a, ecore=ecab, itype=itype, anag=anag, se_int_control=se_int_control, &
1045 se_taper=se_taper, store_int_env=store_int_env)
1046 ecore2 = ecore2 + ecab(1) + ecab(2)
1047 ELSE IF (nspins == 2) THEN
1048 ecab = 0._dp
1049 CALL fock2_1el(se_kind_a, se_kind_b, rij, ksa_block_a, ksb_block_a, &
1050 pa_block_a, pb_block_a, ecore=ecab, itype=itype, anag=anag, &
1051 se_int_control=se_int_control, se_taper=se_taper, store_int_env=store_int_env)
1052 CALL fock2_1el(se_kind_a, se_kind_b, rij, ksa_block_b, ksb_block_b, &
1053 pa_b, pb_b, ecore=ecab, itype=itype, anag=anag, se_int_control=se_int_control, &
1054 se_taper=se_taper, store_int_env=store_int_env)
1055 ecore2 = ecore2 + ecab(1) + ecab(2)
1056 END IF
1057 IF (atener) THEN
1058 atprop%atecoul(iatom) = atprop%atecoul(iatom) + ecab(1) + 0.5_dp*enuc
1059 atprop%atecoul(jatom) = atprop%atecoul(jatom) + ecab(2) + 0.5_dp*enuc
1060 END IF
1061 ! Coulomb Terms
1062 IF (nspins == 1) THEN
1063 CALL fock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, ksa_block_a, p_block_tot_b, &
1064 ksb_block_a, factor=0.5_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
1065 store_int_env=store_int_env)
1066 ELSE IF (nspins == 2) THEN
1067 CALL fock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, ksa_block_a, p_block_tot_b, &
1068 ksb_block_a, factor=1.0_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
1069 store_int_env=store_int_env)
1070
1071 CALL fock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, ksa_block_b, p_block_tot_b, &
1072 ksb_block_b, factor=1.0_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
1073 store_int_env=store_int_env)
1074 END IF
1075
1076 IF (calculate_forces) THEN
1077 atom_a = atom_of_kind(iatom)
1078 atom_b = atom_of_kind(jatom)
1079
1080 ! Evaluate nuclear contribution..
1081 CALL dcorecore_el(se_kind_a, se_kind_b, rij, denuc=force_ab, itype=itype, delta=delta, &
1082 anag=anag, se_int_control=se_int_control, se_taper=se_taper)
1083
1084 ! Derivatives of the Two-centre One-electron terms
1085 IF (nspins == 1) THEN
1086 CALL dfock2_1el(se_kind_a, se_kind_b, rij, pa_a, pb_a, itype=itype, anag=anag, &
1087 se_int_control=se_int_control, se_taper=se_taper, force=force_ab, &
1088 delta=delta)
1089 ELSE IF (nspins == 2) THEN
1090 CALL dfock2_1el(se_kind_a, se_kind_b, rij, pa_block_a, pb_block_a, itype=itype, anag=anag, &
1091 se_int_control=se_int_control, se_taper=se_taper, force=force_ab, delta=delta)
1092 CALL dfock2_1el(se_kind_a, se_kind_b, rij, pa_b, pb_b, itype=itype, anag=anag, &
1093 se_int_control=se_int_control, se_taper=se_taper, force=force_ab, delta=delta)
1094 END IF
1095 IF (use_virial) THEN
1096 CALL virial_pair_force(virial%pv_virial, -1.0_dp, force_ab, rij)
1097 END IF
1098 force_ab = force_ab + force_ab0
1099
1100 ! Sum up force components
1101 force(ikind)%all_potential(1, atom_a) = force(ikind)%all_potential(1, atom_a) - force_ab(1)
1102 force(jkind)%all_potential(1, atom_b) = force(jkind)%all_potential(1, atom_b) + force_ab(1)
1103
1104 force(ikind)%all_potential(2, atom_a) = force(ikind)%all_potential(2, atom_a) - force_ab(2)
1105 force(jkind)%all_potential(2, atom_b) = force(jkind)%all_potential(2, atom_b) + force_ab(2)
1106
1107 force(ikind)%all_potential(3, atom_a) = force(ikind)%all_potential(3, atom_a) - force_ab(3)
1108 force(jkind)%all_potential(3, atom_b) = force(jkind)%all_potential(3, atom_b) + force_ab(3)
1109
1110 ! Derivatives of the Coulomb Terms
1111 force_ab = 0._dp
1112 IF (nspins == 1) THEN
1113 CALL dfock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, p_block_tot_b, factor=0.25_dp, &
1114 anag=anag, se_int_control=se_int_control, se_taper=se_taper, force=force_ab, delta=delta)
1115 ELSE IF (nspins == 2) THEN
1116 CALL dfock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, p_block_tot_b, factor=0.50_dp, &
1117 anag=anag, se_int_control=se_int_control, se_taper=se_taper, force=force_ab, delta=delta)
1118
1119 CALL dfock2c(se_kind_a, se_kind_b, rij, switch, p_block_tot_a, p_block_tot_b, factor=0.50_dp, &
1120 anag=anag, se_int_control=se_int_control, se_taper=se_taper, force=force_ab, delta=delta)
1121 END IF
1122 IF (switch) THEN
1123 force_ab(1) = -force_ab(1)
1124 force_ab(2) = -force_ab(2)
1125 force_ab(3) = -force_ab(3)
1126 END IF
1127 IF (use_virial) THEN
1128 CALL virial_pair_force(virial%pv_virial, -1.0_dp, force_ab, rij)
1129 END IF
1130
1131 ! Sum up force components
1132 force(ikind)%rho_elec(1, atom_a) = force(ikind)%rho_elec(1, atom_a) - force_ab(1)
1133 force(jkind)%rho_elec(1, atom_b) = force(jkind)%rho_elec(1, atom_b) + force_ab(1)
1134
1135 force(ikind)%rho_elec(2, atom_a) = force(ikind)%rho_elec(2, atom_a) - force_ab(2)
1136 force(jkind)%rho_elec(2, atom_b) = force(jkind)%rho_elec(2, atom_b) + force_ab(2)
1137
1138 force(ikind)%rho_elec(3, atom_a) = force(ikind)%rho_elec(3, atom_a) - force_ab(3)
1139 force(jkind)%rho_elec(3, atom_b) = force(jkind)%rho_elec(3, atom_b) + force_ab(3)
1140 END IF
1141 CASE DEFAULT
1142 cpabort("")
1143 END SELECT
1144 END IF
1145 END DO
1146 CALL neighbor_list_iterator_release(nl_iterator)
1147
1148 DEALLOCATE (se_kind_list, se_defined, se_natorb)
1149
1150 ! Sum-up Virial constribution (long-range correction)
1151 IF (use_virial) THEN
1152 pv_glob(1, 1) = pv_glob(1, 1) + ptens11
1153 pv_glob(1, 2) = pv_glob(1, 2) + (ptens12 + ptens21)*0.5_dp
1154 pv_glob(1, 3) = pv_glob(1, 3) + (ptens13 + ptens31)*0.5_dp
1155 pv_glob(2, 1) = pv_glob(1, 2)
1156 pv_glob(2, 2) = pv_glob(2, 2) + ptens22
1157 pv_glob(2, 3) = pv_glob(2, 3) + (ptens23 + ptens32)*0.5_dp
1158 pv_glob(3, 1) = pv_glob(1, 3)
1159 pv_glob(3, 2) = pv_glob(2, 3)
1160 pv_glob(3, 3) = pv_glob(3, 3) + ptens33
1161 END IF
1162
1163 ! collect information on potential, field, field gradient
1164 CALL para_env%sum(efield0)
1165 CALL para_env%sum(efield1)
1166 CALL para_env%sum(efield2)
1167 se_nddo_mpole%efield0 = se_nddo_mpole%efield0 - efield0
1168 se_nddo_mpole%efield1 = se_nddo_mpole%efield1 - efield1
1169 se_nddo_mpole%efield2 = se_nddo_mpole%efield2 - efield2
1170 ! deallocate working arrays
1171 DEALLOCATE (efield0)
1172 DEALLOCATE (efield1)
1173 DEALLOCATE (efield2)
1174
1175 ! Corrections for two-centers one-electron terms + nuclear terms
1176 CALL para_env%sum(enuclear)
1177 CALL para_env%sum(ecore2)
1178 energy%hartree = energy%hartree + ecore2
1179 energy%core_overlap = enuclear
1180 CALL finalize_se_taper(se_taper)
1181 CALL timestop(handle)
1182 END SUBROUTINE build_fock_matrix_coul_lrc
1183
1184! **************************************************************************************************
1185!> \brief Construction of the residual part (1/R^3) of the Coulomb long-range
1186!> term of the Fock matrix
1187!> The 1/R^3 correction works in real-space strictly on the zero-cell,
1188!> in order to avoid more parameters to be provided in the input..
1189!> \param qs_env ...
1190!> \param ks_matrix ...
1191!> \param matrix_p ...
1192!> \param energy ...
1193!> \param calculate_forces ...
1194!> \author Teodoro Laino [tlaino] - 12.2008
1195! **************************************************************************************************
1196 SUBROUTINE build_fock_matrix_coul_lr_r3(qs_env, ks_matrix, matrix_p, energy, calculate_forces)
1197 TYPE(qs_environment_type), POINTER :: qs_env
1198 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ks_matrix, matrix_p
1199 TYPE(qs_energy_type), POINTER :: energy
1200 LOGICAL, INTENT(in) :: calculate_forces
1201
1202 CHARACTER(len=*), PARAMETER :: routinen = 'build_fock_matrix_coul_lr_r3'
1203
1204 INTEGER :: atom_a, atom_b, ewald_type, handle, iatom, ikind, inode, ispin, itype, jatom, &
1205 jkind, natoms, natorb_a, natorb_a2, natorb_b, natorb_b2, nkind, nlocal_particles, nspins
1206 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, se_natorb
1207 LOGICAL :: anag, atener, check, defined, found, &
1208 switch
1209 LOGICAL, ALLOCATABLE, DIMENSION(:) :: se_defined
1210 REAL(kind=dp) :: dr1, ecore2, r2inv, r3inv, rinv
1211 REAL(kind=dp), DIMENSION(2) :: ecab
1212 REAL(kind=dp), DIMENSION(2025) :: pa_a, pa_b, pb_a, pb_b
1213 REAL(kind=dp), DIMENSION(3) :: dr3inv, force_ab, rij
1214 REAL(kind=dp), DIMENSION(45, 45) :: p_block_tot_a, p_block_tot_b
1215 REAL(kind=dp), DIMENSION(:, :), POINTER :: ksa_block_a, ksa_block_b, ksb_block_a, &
1216 ksb_block_b, pa_block_a, pa_block_b, &
1217 pb_block_a, pb_block_b
1218 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1219 TYPE(atprop_type), POINTER :: atprop
1220 TYPE(cell_type), POINTER :: cell
1221 TYPE(cp_logger_type), POINTER :: logger
1222 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: diagmat_ks, diagmat_p
1223 TYPE(dft_control_type), POINTER :: dft_control
1224 TYPE(distribution_1d_type), POINTER :: local_particles
1225 TYPE(ewald_environment_type), POINTER :: ewald_env
1226 TYPE(ewald_pw_type), POINTER :: ewald_pw
1227 TYPE(fist_nonbond_env_type), POINTER :: se_nonbond_env
1228 TYPE(mp_para_env_type), POINTER :: para_env
1229 TYPE(nddo_mpole_type), POINTER :: se_nddo_mpole
1231 DIMENSION(:), POINTER :: nl_iterator
1232 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1233 POINTER :: sab_orb
1234 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1235 TYPE(qs_force_type), DIMENSION(:), POINTER :: force
1236 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1237 TYPE(section_vals_type), POINTER :: se_section
1238 TYPE(semi_empirical_control_type), POINTER :: se_control
1239 TYPE(semi_empirical_p_type), DIMENSION(:), POINTER :: se_kind_list
1240 TYPE(semi_empirical_type), POINTER :: se_kind_a, se_kind_b
1241
1242 CALL timeset(routinen, handle)
1243
1244 CALL get_qs_env(qs_env=qs_env) !sm->dbcsr
1245
1246 NULLIFY (dft_control, cell, force, particle_set, diagmat_ks, &
1247 diagmat_p, local_particles, se_control, ewald_env, ewald_pw, &
1248 se_nddo_mpole, se_nonbond_env, se_section, sab_orb, logger, atprop)
1249
1250 logger => cp_get_default_logger()
1251 CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, cell=cell, para_env=para_env, &
1252 atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set, particle_set=particle_set, &
1253 ewald_env=ewald_env, atprop=atprop, &
1254 local_particles=local_particles, ewald_pw=ewald_pw, se_nddo_mpole=se_nddo_mpole, &
1255 se_nonbond_env=se_nonbond_env, sab_orb=sab_orb)
1256
1257 nlocal_particles = sum(local_particles%n_el(:))
1258 natoms = SIZE(particle_set)
1259 CALL ewald_env_get(ewald_env, ewald_type=ewald_type)
1260 SELECT CASE (ewald_type)
1261 CASE (do_ewald_ewald)
1262 ! Do Nothing
1263 CASE DEFAULT
1264 cpabort("Periodic SE implemented only for standard EWALD sums.")
1265 END SELECT
1266
1267 ! Parameters
1268 se_section => section_vals_get_subs_vals(qs_env%input, "DFT%QS%SE")
1269 se_control => dft_control%qs_control%se_control
1270 anag = se_control%analytical_gradients
1271 atener = atprop%energy
1272
1273 nspins = dft_control%nspins
1274 cpassert(ASSOCIATED(matrix_p))
1275 cpassert(SIZE(ks_matrix) > 0)
1276
1277 CALL dbcsr_allocate_matrix_set(diagmat_ks, nspins)
1278 CALL dbcsr_allocate_matrix_set(diagmat_p, nspins)
1279
1280 nkind = SIZE(atomic_kind_set)
1281 DO ispin = 1, nspins
1282 ! Allocate diagonal block matrices
1283 ALLOCATE (diagmat_p(ispin)%matrix, diagmat_ks(ispin)%matrix) !sm->dbcsr
1284 CALL dbcsr_get_block_diag(matrix_p(ispin)%matrix, diagmat_p(ispin)%matrix)
1285 CALL dbcsr_get_block_diag(ks_matrix(ispin)%matrix, diagmat_ks(ispin)%matrix)
1286 CALL dbcsr_set(diagmat_ks(ispin)%matrix, 0.0_dp)
1287 CALL dbcsr_replicate_all(diagmat_p(ispin)%matrix)
1288 CALL dbcsr_replicate_all(diagmat_ks(ispin)%matrix)
1289 END DO
1290
1291 ! Possibly compute forces
1292 IF (calculate_forces) THEN
1293 CALL get_qs_env(qs_env=qs_env, force=force)
1294 CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, atom_of_kind=atom_of_kind)
1295 END IF
1296 itype = get_se_type(dft_control%qs_control%method_id)
1297
1298 ecore2 = 0.0_dp
1299 ! Real space part of the 1/R^3 sum
1300 ALLOCATE (se_defined(nkind), se_kind_list(nkind), se_natorb(nkind))
1301 DO ikind = 1, nkind
1302 CALL get_qs_kind(qs_kind_set(ikind), se_parameter=se_kind_a)
1303 se_kind_list(ikind)%se_param => se_kind_a
1304 CALL get_se_param(se_kind_a, defined=defined, natorb=natorb_a)
1305 se_defined(ikind) = (defined .AND. natorb_a >= 1)
1306 se_natorb(ikind) = natorb_a
1307 END DO
1308
1309 CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
1310 DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
1311 CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, iatom=iatom, jatom=jatom, inode=inode, r=rij)
1312 IF (.NOT. se_defined(ikind)) cycle
1313 IF (.NOT. se_defined(jkind)) cycle
1314 se_kind_a => se_kind_list(ikind)%se_param
1315 se_kind_b => se_kind_list(jkind)%se_param
1316 natorb_a = se_natorb(ikind)
1317 natorb_b = se_natorb(jkind)
1318 natorb_a2 = natorb_a**2
1319 natorb_b2 = natorb_b**2
1320
1321 IF (inode == 1) THEN
1322 CALL dbcsr_get_block_p(matrix=diagmat_p(1)%matrix, &
1323 row=iatom, col=iatom, block=pa_block_a, found=found)
1324 cpassert(ASSOCIATED(pa_block_a))
1325 check = (SIZE(pa_block_a, 1) == natorb_a) .AND. (SIZE(pa_block_a, 2) == natorb_a)
1326 cpassert(check)
1327 CALL dbcsr_get_block_p(matrix=diagmat_ks(1)%matrix, &
1328 row=iatom, col=iatom, block=ksa_block_a, found=found)
1329 cpassert(ASSOCIATED(ksa_block_a))
1330 p_block_tot_a(1:natorb_a, 1:natorb_a) = 2.0_dp*pa_block_a
1331 pa_a(1:natorb_a2) = reshape(pa_block_a, (/natorb_a2/))
1332 IF (nspins == 2) THEN
1333 CALL dbcsr_get_block_p(matrix=diagmat_p(2)%matrix, &
1334 row=iatom, col=iatom, block=pa_block_b, found=found)
1335 cpassert(ASSOCIATED(pa_block_b))
1336 check = (SIZE(pa_block_b, 1) == natorb_a) .AND. (SIZE(pa_block_b, 2) == natorb_a)
1337 cpassert(check)
1338 CALL dbcsr_get_block_p(matrix=diagmat_ks(2)%matrix, &
1339 row=iatom, col=iatom, block=ksa_block_b, found=found)
1340 cpassert(ASSOCIATED(ksa_block_b))
1341 p_block_tot_a(1:natorb_a, 1:natorb_a) = pa_block_a + pa_block_b
1342 pa_b(1:natorb_a2) = reshape(pa_block_b, (/natorb_a2/))
1343 END IF
1344 END IF
1345
1346 dr1 = dot_product(rij, rij)
1347 IF (dr1 > rij_threshold) THEN
1348 ! Determine the order of the atoms, and in case switch them..
1349 IF (iatom <= jatom) THEN
1350 switch = .false.
1351 ELSE
1352 switch = .true.
1353 END IF
1354 ! Retrieve blocks for KS and P
1355 CALL dbcsr_get_block_p(matrix=diagmat_p(1)%matrix, &
1356 row=jatom, col=jatom, block=pb_block_a, found=found)
1357 cpassert(ASSOCIATED(pb_block_a))
1358 check = (SIZE(pb_block_a, 1) == natorb_b) .AND. (SIZE(pb_block_a, 2) == natorb_b)
1359 cpassert(check)
1360 CALL dbcsr_get_block_p(matrix=diagmat_ks(1)%matrix, &
1361 row=jatom, col=jatom, block=ksb_block_a, found=found)
1362 cpassert(ASSOCIATED(ksb_block_a))
1363 p_block_tot_b(1:natorb_b, 1:natorb_b) = 2.0_dp*pb_block_a
1364 pb_a(1:natorb_b2) = reshape(pb_block_a, (/natorb_b2/))
1365 ! Handle more than one configuration
1366 IF (nspins == 2) THEN
1367 CALL dbcsr_get_block_p(matrix=diagmat_p(2)%matrix, &
1368 row=jatom, col=jatom, block=pb_block_b, found=found)
1369 cpassert(ASSOCIATED(pb_block_b))
1370 check = (SIZE(pb_block_b, 1) == natorb_b) .AND. (SIZE(pb_block_b, 2) == natorb_b)
1371 cpassert(check)
1372 CALL dbcsr_get_block_p(matrix=diagmat_ks(2)%matrix, &
1373 row=jatom, col=jatom, block=ksb_block_b, found=found)
1374 cpassert(ASSOCIATED(ksb_block_b))
1375 check = (SIZE(pb_block_a, 1) == SIZE(pb_block_b, 1)) .AND. (SIZE(pb_block_a, 2) == SIZE(pb_block_b, 2))
1376 cpassert(check)
1377 p_block_tot_b(1:natorb_b, 1:natorb_b) = pb_block_a + pb_block_b
1378 pb_b(1:natorb_b2) = reshape(pb_block_b, (/natorb_b2/))
1379 END IF
1380
1381 SELECT CASE (dft_control%qs_control%method_id)
1384
1385 ! Pre-compute some quantities..
1386 r2inv = 1.0_dp/dr1
1387 rinv = sqrt(r2inv)
1388 r3inv = rinv**3
1389
1390 ! Two-centers One-electron terms
1391 IF (nspins == 1) THEN
1392 ecab = 0._dp
1393 CALL fock2_1el_r3(se_kind_a, se_kind_b, ksa_block_a, ksb_block_a, pa_a, pb_a, &
1394 ecore=ecab, e1b=se_kind_a%expns3_int(jkind)%expns3%e1b, &
1395 e2a=se_kind_a%expns3_int(jkind)%expns3%e2a, rp=r3inv)
1396 ecore2 = ecore2 + ecab(1) + ecab(2)
1397 ELSE IF (nspins == 2) THEN
1398 ecab = 0._dp
1399 CALL fock2_1el_r3(se_kind_a, se_kind_b, ksa_block_a, ksb_block_a, pa_block_a, &
1400 pb_block_a, ecore=ecab, e1b=se_kind_a%expns3_int(jkind)%expns3%e1b, &
1401 e2a=se_kind_a%expns3_int(jkind)%expns3%e2a, rp=r3inv)
1402
1403 CALL fock2_1el_r3(se_kind_a, se_kind_b, ksa_block_b, ksb_block_b, pa_b, pb_b, &
1404 ecore=ecab, e1b=se_kind_a%expns3_int(jkind)%expns3%e1b, &
1405 e2a=se_kind_a%expns3_int(jkind)%expns3%e2a, rp=r3inv)
1406 ecore2 = ecore2 + ecab(1) + ecab(2)
1407 END IF
1408 IF (atener) THEN
1409 atprop%atecoul(iatom) = atprop%atecoul(iatom) + ecab(1)
1410 atprop%atecoul(jatom) = atprop%atecoul(jatom) + ecab(2)
1411 END IF
1412 ! Coulomb Terms
1413 IF (nspins == 1) THEN
1414 CALL fock2c_r3(se_kind_a, se_kind_b, switch, p_block_tot_a, ksa_block_a, p_block_tot_b, &
1415 ksb_block_a, factor=0.5_dp, w=se_kind_a%expns3_int(jkind)%expns3%w, rp=r3inv)
1416 ELSE IF (nspins == 2) THEN
1417 CALL fock2c_r3(se_kind_a, se_kind_b, switch, p_block_tot_a, ksa_block_a, p_block_tot_b, &
1418 ksb_block_a, factor=1.0_dp, w=se_kind_a%expns3_int(jkind)%expns3%w, rp=r3inv)
1419
1420 CALL fock2c_r3(se_kind_a, se_kind_b, switch, p_block_tot_a, ksa_block_b, p_block_tot_b, &
1421 ksb_block_b, factor=1.0_dp, w=se_kind_a%expns3_int(jkind)%expns3%w, rp=r3inv)
1422 END IF
1423
1424 ! Compute forces if requested
1425 IF (calculate_forces) THEN
1426 dr3inv = -3.0_dp*rij*r3inv*r2inv
1427 atom_a = atom_of_kind(iatom)
1428 atom_b = atom_of_kind(jatom)
1429
1430 force_ab = 0.0_dp
1431 ! Derivatives of the One-centre One-electron terms
1432 IF (nspins == 1) THEN
1433 CALL dfock2_1el_r3(se_kind_a, se_kind_b, dr3inv, pa_a, pb_a, force_ab, &
1434 se_kind_a%expns3_int(jkind)%expns3%e1b, se_kind_a%expns3_int(jkind)%expns3%e2a)
1435 ELSE IF (nspins == 2) THEN
1436 CALL dfock2_1el_r3(se_kind_a, se_kind_b, dr3inv, pa_block_a, pb_block_a, force_ab, &
1437 se_kind_a%expns3_int(jkind)%expns3%e1b, se_kind_a%expns3_int(jkind)%expns3%e2a)
1438
1439 CALL dfock2_1el_r3(se_kind_a, se_kind_b, dr3inv, pa_b, pb_b, force_ab, &
1440 se_kind_a%expns3_int(jkind)%expns3%e1b, se_kind_a%expns3_int(jkind)%expns3%e2a)
1441 END IF
1442
1443 ! Sum up force components
1444 force(ikind)%all_potential(1, atom_a) = force(ikind)%all_potential(1, atom_a) - force_ab(1)
1445 force(jkind)%all_potential(1, atom_b) = force(jkind)%all_potential(1, atom_b) + force_ab(1)
1446
1447 force(ikind)%all_potential(2, atom_a) = force(ikind)%all_potential(2, atom_a) - force_ab(2)
1448 force(jkind)%all_potential(2, atom_b) = force(jkind)%all_potential(2, atom_b) + force_ab(2)
1449
1450 force(ikind)%all_potential(3, atom_a) = force(ikind)%all_potential(3, atom_a) - force_ab(3)
1451 force(jkind)%all_potential(3, atom_b) = force(jkind)%all_potential(3, atom_b) + force_ab(3)
1452
1453 ! Derivatives of the Coulomb Terms
1454 force_ab = 0.0_dp
1455 IF (nspins == 1) THEN
1456 CALL dfock2c_r3(se_kind_a, se_kind_b, switch, p_block_tot_a, p_block_tot_b, factor=0.25_dp, &
1457 w=se_kind_a%expns3_int(jkind)%expns3%w, drp=dr3inv, force=force_ab)
1458 ELSE IF (nspins == 2) THEN
1459 CALL dfock2c_r3(se_kind_a, se_kind_b, switch, p_block_tot_a, p_block_tot_b, factor=0.50_dp, &
1460 w=se_kind_a%expns3_int(jkind)%expns3%w, drp=dr3inv, force=force_ab)
1461
1462 CALL dfock2c_r3(se_kind_a, se_kind_b, switch, p_block_tot_a, p_block_tot_b, factor=0.50_dp, &
1463 w=se_kind_a%expns3_int(jkind)%expns3%w, drp=dr3inv, force=force_ab)
1464 END IF
1465
1466 ! Sum up force components
1467 force(ikind)%rho_elec(1, atom_a) = force(ikind)%rho_elec(1, atom_a) - force_ab(1)
1468 force(jkind)%rho_elec(1, atom_b) = force(jkind)%rho_elec(1, atom_b) + force_ab(1)
1469
1470 force(ikind)%rho_elec(2, atom_a) = force(ikind)%rho_elec(2, atom_a) - force_ab(2)
1471 force(jkind)%rho_elec(2, atom_b) = force(jkind)%rho_elec(2, atom_b) + force_ab(2)
1472
1473 force(ikind)%rho_elec(3, atom_a) = force(ikind)%rho_elec(3, atom_a) - force_ab(3)
1474 force(jkind)%rho_elec(3, atom_b) = force(jkind)%rho_elec(3, atom_b) + force_ab(3)
1475 END IF
1476 CASE DEFAULT
1477 cpabort("")
1478 END SELECT
1479 END IF
1480 END DO
1481 CALL neighbor_list_iterator_release(nl_iterator)
1482
1483 DEALLOCATE (se_kind_list, se_defined, se_natorb)
1484
1485 DO ispin = 1, nspins
1486 CALL dbcsr_sum_replicated(diagmat_ks(ispin)%matrix)
1487 CALL dbcsr_distribute(diagmat_ks(ispin)%matrix)
1488 CALL dbcsr_add(ks_matrix(ispin)%matrix, diagmat_ks(ispin)%matrix, &
1489 1.0_dp, 1.0_dp)
1490 END DO
1491 CALL dbcsr_deallocate_matrix_set(diagmat_p)
1492 CALL dbcsr_deallocate_matrix_set(diagmat_ks)
1493
1494 ! Two-centers one-electron terms
1495 CALL para_env%sum(ecore2)
1496 energy%hartree = energy%hartree + ecore2
1497
1498 CALL timestop(handle)
1499 END SUBROUTINE build_fock_matrix_coul_lr_r3
1500
1501END MODULE se_fock_matrix_coulomb
1502
static GRID_HOST_DEVICE double fac(const int i)
Factorial function, e.g. fac(5) = 5! = 120.
Definition grid_common.h:51
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind_set(atomic_kind_set, atom_of_kind, kind_of, natom_of_kind, maxatom, natom, nshell, fist_potential_present, shell_present, shell_adiabatic, shell_check_distance, damping_present)
Get attributes of an atomic kind set.
Holds information on atomic properties.
Handles all functions related to the CELL.
Definition cell_types.F:15
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
subroutine, public dbcsr_get_block_p(matrix, row, col, block, found, row_size, col_size)
...
subroutine, public dbcsr_replicate_all(matrix)
...
subroutine, public dbcsr_distribute(matrix)
...
subroutine, public dbcsr_sum_replicated(matrix)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_add(matrix_a, matrix_b, alpha_scalar, beta_scalar)
...
subroutine, public dbcsr_get_block_diag(matrix, diag)
Copies the diagonal blocks of matrix into diag.
DBCSR operations in CP2K.
various routines to log and control the output. The idea is that decisions about where to log should ...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
stores a lists of integer that are local to a processor. The idea is that these integers represent ob...
subroutine, public ewald_env_get(ewald_env, ewald_type, alpha, eps_pol, epsilon, gmax, ns_max, o_spline, group, para_env, poisson_section, precs, rcut, do_multipoles, max_multipole, do_ipol, max_ipol_iter, interaction_cutoffs, cell_hmat)
Purpose: Get the EWALD environment.
subroutine, public ewald_pw_get(ewald_pw, pw_big_pool, pw_small_pool, rs_desc, poisson_env, dg)
get the ewald_pw environment to the correct program.
Treats the electrostatic for multipoles (up to quadrupoles)
recursive subroutine, public ewald_multipole_evaluate(ewald_env, ewald_pw, nonbond_env, cell, particle_set, local_particles, energy_local, energy_glob, e_neut, e_self, task, do_correction_bonded, do_forces, do_stress, do_efield, radii, charges, dipoles, quadrupoles, forces_local, forces_glob, pv_local, pv_glob, efield0, efield1, efield2, iw, do_debug, atomic_kind_set, mm_section)
Computes the potential and the force for a lattice sum of multipoles (up to quadrupole)
subroutine, public list_control(atomic_kind_set, particle_set, local_particles, cell, fist_nonbond_env, para_env, mm_section, shell_particle_set, core_particle_set, force_update, exclusions)
...
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public do_method_pdg
integer, parameter, public do_method_pnnl
integer, parameter, public do_method_rm1
integer, parameter, public do_method_pm3
integer, parameter, public do_method_mndo
integer, parameter, public do_method_mndod
integer, parameter, public do_method_am1
integer, parameter, public do_se_is_slater
integer, parameter, public do_method_pm6fm
integer, parameter, public do_method_pm6
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Interface to the message passing library MPI.
Multipole structure: for multipole (fixed and induced) in FF based MD.
integer, parameter, public do_multipole_quadrupole
integer, parameter, public do_multipole_dipole
integer, parameter, public do_multipole_charge
integer, parameter, public do_multipole_none
Define the data structure for the particle information.
functions related to the poisson solver on regular grids
integer, parameter, public do_ewald_ewald
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, ecoul_1c, rho0_s_rs, rho0_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs)
Get the QUICKSTEP environment.
Define the quickstep kind type and their sub types.
subroutine, public get_qs_kind(qs_kind, basis_set, basis_type, ncgf, nsgf, all_potential, tnadd_potential, gth_potential, sgp_potential, upf_potential, se_parameter, dftb_parameter, xtb_parameter, dftb3_param, zatom, zeff, elec_conf, mao, lmax_dftb, alpha_core_charge, ccore_charge, core_charge, core_charge_radius, paw_proj_set, paw_atom, hard_radius, hard0_radius, max_rad_local, covalent_radius, vdw_radius, gpw_type_forced, harmonics, max_iso_not0, max_s_harm, grid_atom, ngrid_ang, ngrid_rad, lmax_rho0, dft_plus_u_atom, l_of_dft_plus_u, n_of_dft_plus_u, u_minus_j, u_of_dft_plus_u, j_of_dft_plus_u, alpha_of_dft_plus_u, beta_of_dft_plus_u, j0_of_dft_plus_u, occupation_of_dft_plus_u, dispersion, bs_occupation, magnetization, no_optimize, addel, laddel, naddel, orbitals, max_scf, eps_scf, smear, u_ramping, u_minus_j_target, eps_u_ramping, init_u_ramping_each_scf, reltmat, ghost, floating, name, element_symbol, pao_basis_size, pao_model_file, pao_potentials, pao_descriptors, nelec)
Get attributes of an atomic kind.
Define the neighbor list data types and the corresponding functionality.
subroutine, public neighbor_list_iterator_create(iterator_set, nl, search, nthread)
Neighbor list iterator functions.
subroutine, public neighbor_list_iterator_release(iterator_set)
...
integer function, public neighbor_list_iterate(iterator_set, mepos)
...
subroutine, public get_iterator_info(iterator_set, mepos, ikind, jkind, nkind, ilist, nlist, inode, nnode, iatom, jatom, r, cell)
...
Module that collects all Coulomb parts of the fock matrix construction.
subroutine, public build_fock_matrix_coulomb(qs_env, ks_matrix, matrix_p, energy, calculate_forces, store_int_env)
Construction of the Coulomb part of the Fock matrix.
subroutine, public build_fock_matrix_coul_lr_r3(qs_env, ks_matrix, matrix_p, energy, calculate_forces)
Construction of the residual part (1/R^3) of the Coulomb long-range term of the Fock matrix The 1/R^3...
subroutine, public build_fock_matrix_coulomb_lr(qs_env, ks_matrix, matrix_p, energy, calculate_forces, store_int_env)
Long-Range part for SE Coulomb interactions.
Provides the low level routines to build both the exchange and the Coulomb Fock matrices....
subroutine, public fock2c_r3(sepi, sepj, switch, pi_tot, fi_mat, pj_tot, fj_mat, factor, w, rp)
Construction of 2-center Fock Matrix - Coulomb Terms for the residual (1/R^3) integral part.
subroutine, public fock2_1el_ew(sep, rij, ks_block, p_block, ecore, itype, anag, se_int_control, se_taper, store_int_env)
Construction of 2-center 1-electron Fock Matrix (Ewald self term)
subroutine, public dfock2c(sepi, sepj, rij, switch, pi_tot, pj_tot, factor, anag, se_int_control, se_taper, force, delta)
Derivatives of 2-center Fock Matrix - Coulomb Terms.
subroutine, public fock2_1el_r3(sepi, sepj, ksi_block, ksj_block, pi_block, pj_block, e1b, e2a, ecore, rp)
Construction of 2-center 1-electron Fock Matrix for the residual (1/R^3) integral part.
subroutine, public dfock2c_r3(sepi, sepj, switch, pi_tot, pj_tot, factor, w, drp, force)
Derivatives of 2-center Fock Matrix - Coulomb Terms for the residual (1/R^3) integral part.
subroutine, public fock2c(sepi, sepj, rij, switch, pi_tot, fi_mat, pj_tot, fj_mat, factor, anag, se_int_control, se_taper, store_int_env)
Construction of 2-center Fock Matrix - Coulomb Terms.
subroutine, public se_coulomb_ij_interaction(atom_a, atom_b, my_task, do_forces, do_efield, do_stress, charges, dipoles, quadrupoles, force_ab, efield0, efield1, efield2, rab2, rab, integral_value, ptens11, ptens12, ptens13, ptens21, ptens22, ptens23, ptens31, ptens32, ptens33)
Coulomb interaction multipolar correction.
subroutine, public dfock2_1el_r3(sepi, sepj, drp, pi_block, pj_block, force, e1b, e2a)
Derivatives of 2-center 1-electron Fock Matrix residual (1/R^3) integral part.
subroutine, public fock2_1el(sepi, sepj, rij, ksi_block, ksj_block, pi_block, pj_block, ecore, itype, anag, se_int_control, se_taper, store_int_env)
Construction of 2-center 1-electron Fock Matrix.
subroutine, public dfock2_1el(sepi, sepj, rij, pi_block, pj_block, itype, anag, se_int_control, se_taper, force, delta)
Derivatives of 2-center 1-electron Fock Matrix.
subroutine, public fock2c_ew(sep, rij, p_tot, f_mat, factor, anag, se_int_control, se_taper, store_int_env)
Construction of 2-center Fock Matrix - Coulomb Self Terms (Ewald)
Arrays of parameters used in the semi-empirical calculations \References Everywhere in this module TC...
real(kind=dp), parameter, public rij_threshold
integer, dimension(9), public se_orbital_pointer
Set of wrappers for semi-empirical analytical/numerical Integrals routines.
subroutine, public dcorecore_el(sepi, sepj, rij, denuc, itype, delta, anag, se_int_control, se_taper)
wrapper for numerical/analytical routines core-core electrostatic (only) integrals derivatives
subroutine, public corecore_el(sepi, sepj, rij, enuc, itype, anag, se_int_control, se_taper)
wrapper for numerical/analytical routines core-core electrostatic (only) integrals
Setup and Methods for semi-empirical multipole types.
subroutine, public quadrupole_sph_to_cart(qcart, qsph)
Transforms the quadrupole components from sphericals to cartesians.
Definition of the semi empirical multipole integral expansions types.
Type to store integrals for semi-empirical calculations.
Definition of the semi empirical parameter types.
subroutine, public setup_se_int_control_type(se_int_control, shortrange, do_ewald_r3, do_ewald_gks, integral_screening, max_multipole, pc_coulomb_int)
Setup the Semiempirical integral control type.
subroutine, public get_se_param(sep, name, typ, defined, z, zeff, natorb, eheat, beta, sto_exponents, uss, upp, udd, uff, alp, eisol, gss, gsp, gpp, gp2, acoul, nr, de, ass, asp, app, hsp, gsd, gpd, gdd, ppddg, dpddg, ngauss)
Get info from the semi-empirical type.
Working with the semi empirical parameter types.
subroutine, public finalize_se_taper(se_taper)
Finalizes the semi-empirical taper for a chunk calculation.
integer function, public get_se_type(se_method)
Gives back the unique semi_empirical METHOD type.
subroutine, public initialize_se_taper(se_taper, coulomb, exchange, lr_corr)
Initializes the semi-empirical taper for a chunk calculation.
pure subroutine, public virial_pair_force(pv_virial, f0, force, rab)
Computes the contribution to the stress tensor from two-body pair-wise forces.
Provides all information about an atomic kind.
type for the atomic properties
Type defining parameters related to the simulation cell.
Definition cell_types.F:55
type of a logger, at the moment it contains just a print level starting at which level it should be l...
structure to store local (to a processor) ordered lists of integers.
stores all the informations relevant to an mpi environment
Provides all information about a quickstep kind.
Global Multipolar NDDO information type.
Semi-empirical integral multipole expansion type.
Taper type use in semi-empirical calculations.