Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 : MODULE qs_vcd_ao
8 : USE ai_contraction, ONLY: block_add,&
9 : contraction
10 : USE ai_kinetic, ONLY: kinetic
11 : USE ai_overlap_ppl, ONLY: ppl_integral
12 : USE ao_util, ONLY: exp_radius_very_extended
13 : USE atomic_kind_types, ONLY: atomic_kind_type,&
14 : get_atomic_kind_set
15 : USE basis_set_types, ONLY: get_gto_basis_set,&
16 : gto_basis_set_p_type,&
17 : gto_basis_set_type
18 : USE block_p_types, ONLY: block_p_type
19 : USE cell_types, ONLY: cell_type,&
20 : pbc
21 : USE cp_control_types, ONLY: dft_control_type
22 : USE cp_dbcsr_api, ONLY: &
23 : dbcsr_add, dbcsr_copy, dbcsr_desymmetrize, dbcsr_distribution_get, &
24 : dbcsr_distribution_type, dbcsr_finalize, dbcsr_get_block_p, dbcsr_get_info, dbcsr_init_p, &
25 : dbcsr_p_type, dbcsr_scale, dbcsr_set, dbcsr_work_create
26 : USE cp_dbcsr_operations, ONLY: dbcsr_allocate_matrix_set,&
27 : dbcsr_deallocate_matrix_set
28 : USE external_potential_types, ONLY: get_potential,&
29 : gth_potential_type,&
30 : sgp_potential_type
31 : USE gaussian_gridlevels, ONLY: gridlevel_info_type
32 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
33 : section_vals_type
34 : USE kinds, ONLY: default_string_length,&
35 : dp,&
36 : int_8
37 : USE memory_utilities, ONLY: reallocate
38 : USE message_passing, ONLY: mp_comm_type
39 : USE orbital_pointers, ONLY: coset,&
40 : init_orbital_pointers,&
41 : ncoset
42 : USE particle_types, ONLY: particle_type
43 : USE pw_env_types, ONLY: pw_env_get,&
44 : pw_env_type
45 : USE pw_methods, ONLY: pw_axpy,&
46 : pw_zero
47 : USE pw_pool_types, ONLY: pw_pool_type
48 : USE pw_types, ONLY: pw_r3d_rs_type
49 : USE qs_energy_types, ONLY: qs_energy_type
50 : USE qs_environment_types, ONLY: get_qs_env,&
51 : qs_environment_type
52 : USE qs_integral_utils, ONLY: basis_set_list_setup,&
53 : get_memory_usage
54 : USE qs_integrate_potential, ONLY: integrate_pgf_product
55 : USE qs_kind_types, ONLY: get_qs_kind,&
56 : get_qs_kind_set,&
57 : qs_kind_type
58 : USE qs_ks_types, ONLY: qs_ks_env_type
59 : USE qs_linres_types, ONLY: vcd_env_type
60 : USE qs_moments, ONLY: build_local_moment_matrix
61 : USE qs_neighbor_list_types, ONLY: &
62 : get_iterator_info, get_neighbor_list_set_p, neighbor_list_iterate, &
63 : neighbor_list_iterator_create, neighbor_list_iterator_p_type, &
64 : neighbor_list_iterator_release, neighbor_list_set_p_type, nl_set_sub_iterator, &
65 : nl_sub_iterate
66 : USE qs_rho_types, ONLY: qs_rho_type
67 : USE qs_vxc, ONLY: qs_vxc_create
68 : USE realspace_grid_types, ONLY: realspace_grid_type
69 : USE rs_pw_interface, ONLY: potential_pw2rs
70 : USE sap_kind_types, ONLY: alist_type,&
71 : build_sap_ints,&
72 : get_alist,&
73 : release_sap_int,&
74 : sap_int_type,&
75 : sap_sort
76 : USE task_list_types, ONLY: atom_pair_type,&
77 : task_list_type,&
78 : task_type
79 : USE virial_types, ONLY: virial_type
80 :
81 : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num, omp_get_num_threads
82 : !$ USE OMP_LIB, ONLY: omp_lock_kind, &
83 : !$ omp_init_lock, omp_set_lock, &
84 : !$ omp_unset_lock, omp_destroy_lock
85 :
86 : #include "./base/base_uses.f90"
87 :
88 : IMPLICIT NONE
89 :
90 : PRIVATE
91 :
92 : ! *** Global parameters ***
93 :
94 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_vcd_ao'
95 : INTEGER, PARAMETER :: bi_1 = 1, bi_x = 2, bi_y = 3, bi_z = 4, bi_xx = 5, &
96 : bi_xy = 6, bi_xz = 7, bi_yy = 8, bi_yz = 9, bi_zz = 10
97 : INTEGER, DIMENSION(3), PARAMETER :: bi_r = [bi_x, bi_y, bi_z]
98 : INTEGER, DIMENSION(3, 3), PARAMETER :: bi_rr = RESHAPE([bi_xx, bi_xy, bi_xz, bi_xy, bi_yy, bi_yz, &
99 : bi_xz, bi_yz, bi_zz], [3, 3])
100 :
101 : ! *** Public subroutines ***
102 :
103 : PUBLIC :: build_dSdV_matrix, build_com_rpnl_r, &
104 : hr_mult_by_delta_3d, build_dcom_rpnl, &
105 : build_matrix_hr_rh
106 :
107 : CONTAINS
108 :
109 : ! **************************************************************************************************
110 : !> \brief Build the matrix Hr*delta_nu^\lambda - rH*delta_mu^\lambda
111 : !> \param vcd_env ...
112 : !> \param qs_env ...
113 : !> \param rc ...
114 : !> \author Edward Ditler
115 : ! **************************************************************************************************
116 38 : SUBROUTINE build_matrix_hr_rh(vcd_env, qs_env, rc)
117 : TYPE(vcd_env_type) :: vcd_env
118 : TYPE(qs_environment_type), POINTER :: qs_env
119 : REAL(dp), DIMENSION(3) :: rc
120 :
121 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_matrix_hr_rh'
122 : INTEGER, PARAMETER :: ispin = 1
123 :
124 : INTEGER :: handle, i
125 : TYPE(cell_type), POINTER :: cell
126 : TYPE(dft_control_type), POINTER :: dft_control
127 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
128 38 : POINTER :: sab_all, sap_ppnl
129 38 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
130 38 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
131 :
132 38 : CALL timeset(routineN, handle)
133 :
134 : CALL get_qs_env(qs_env=qs_env, &
135 : dft_control=dft_control, &
136 : particle_set=particle_set, &
137 : sab_all=sab_all, &
138 : sap_ppnl=sap_ppnl, &
139 : qs_kind_set=qs_kind_set, &
140 38 : cell=cell)
141 :
142 152 : DO i = 1, 3
143 114 : CALL dbcsr_set(vcd_env%matrix_hr(ispin, i)%matrix, 0._dp)
144 152 : CALL dbcsr_set(vcd_env%matrix_rh(ispin, i)%matrix, 0._dp)
145 : END DO
146 :
147 : ASSOCIATE (matrix_hr_1d => vcd_env%matrix_hr(ispin, 1:3), &
148 : matrix_rh_1d => vcd_env%matrix_rh(ispin, 1:3))
149 : CALL build_rpnl_matrices(matrix_hr_1d, matrix_rh_1d, qs_kind_set, particle_set, sab_all, sap_ppnl, &
150 38 : dft_control%qs_control%eps_ppnl, cell, rc)
151 38 : CALL build_tr_matrices(matrix_hr_1d, matrix_rh_1d, qs_env, qs_kind_set, "ORB", sab_all, rc)
152 38 : CALL build_rcore_matrices(matrix_hr_1d, matrix_rh_1d, qs_env, qs_kind_set, "ORB", sab_all, rc)
153 76 : CALL build_vhxc_matrices(vcd_env%matrix_hr, vcd_env%matrix_rh, qs_env, rc)
154 : END ASSOCIATE
155 :
156 38 : CALL timestop(handle)
157 38 : END SUBROUTINE build_matrix_hr_rh
158 :
159 : ! **************************************************************************************************
160 : !> \brief Build the ordered products V_nl*r and r*V_nl.
161 : !> \param matrix_vr ...
162 : !> \param matrix_rv ...
163 : !> \param qs_kind_set ...
164 : !> \param particle_set ...
165 : !> \param sab_all ...
166 : !> \param sap_ppnl ...
167 : !> \param eps_ppnl ...
168 : !> \param cell ...
169 : !> \param ref_point ...
170 : !> \author Edward Ditler, Tomas Zimmermann
171 : ! **************************************************************************************************
172 38 : SUBROUTINE build_rpnl_matrices(matrix_vr, matrix_rv, qs_kind_set, particle_set, sab_all, sap_ppnl, eps_ppnl, &
173 : cell, ref_point)
174 :
175 : TYPE(dbcsr_p_type), DIMENSION(:) :: matrix_vr, matrix_rv
176 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
177 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
178 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
179 : POINTER :: sab_all, sap_ppnl
180 : REAL(KIND=dp), INTENT(IN) :: eps_ppnl
181 : TYPE(cell_type), INTENT(IN), OPTIONAL, POINTER :: cell
182 : REAL(KIND=dp), DIMENSION(3) :: ref_point
183 :
184 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_rpnl_matrices'
185 :
186 : INTEGER :: handle, i, iab, iac, iatom, ibc, icol, &
187 : ikind, irow, jatom, jkind, kac, kbc, &
188 : kkind, na, natom, nb, nkind, np, slot
189 : INTEGER, DIMENSION(3) :: cell_b
190 : LOGICAL :: found, ppnl_present
191 38 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: achint, acint, bchint, bcint
192 : TYPE(alist_type), POINTER :: alist_ac, alist_bc
193 266 : TYPE(block_p_type), DIMENSION(3) :: blocks_rv, blocks_vr
194 38 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set
195 : TYPE(gto_basis_set_type), POINTER :: orb_basis_set
196 38 : TYPE(sap_int_type), DIMENSION(:), POINTER :: sap_int
197 :
198 : !$ INTEGER(kind=omp_lock_kind), &
199 38 : !$ ALLOCATABLE, DIMENSION(:) :: locks
200 : !$ INTEGER :: lock_num, hash
201 : !$ INTEGER, PARAMETER :: nlock = 501
202 :
203 38 : ppnl_present = ASSOCIATED(sap_ppnl)
204 38 : IF (.NOT. ppnl_present) RETURN
205 :
206 38 : CALL timeset(routineN, handle)
207 38 : nkind = SIZE(qs_kind_set)
208 38 : natom = SIZE(particle_set)
209 :
210 : ! sap_int needs to be shared as multiple threads need to access this
211 38 : NULLIFY (sap_int)
212 266 : ALLOCATE (sap_int(nkind*nkind))
213 190 : DO i = 1, nkind*nkind
214 152 : NULLIFY (sap_int(i)%alist, sap_int(i)%asort, sap_int(i)%aindex)
215 190 : sap_int(i)%nalist = 0
216 : END DO
217 :
218 : MARK_USED(ref_point)
219 : ! "nder" in moment_mode is "order"
220 : CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, nder=1, moment_mode=.TRUE., &
221 38 : particle_set=particle_set, cell=cell, refpoint=ref_point)
222 :
223 : ! *** Set up a sorting index
224 38 : CALL sap_sort(sap_int)
225 :
226 190 : ALLOCATE (basis_set(nkind))
227 114 : DO ikind = 1, nkind
228 76 : CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
229 114 : IF (ASSOCIATED(orb_basis_set)) THEN
230 76 : basis_set(ikind)%gto_basis_set => orb_basis_set
231 : ELSE
232 0 : NULLIFY (basis_set(ikind)%gto_basis_set)
233 : END IF
234 : END DO
235 :
236 : ! *** All integrals needed have been calculated and stored in sap_int
237 : ! *** We now calculate the ordered product matrix elements
238 :
239 : !$OMP PARALLEL &
240 : !$OMP DEFAULT (NONE) &
241 : !$OMP SHARED (basis_set, matrix_vr, matrix_rv, &
242 : !$OMP sap_int, nkind, eps_ppnl, locks, sab_all) &
243 : !$OMP PRIVATE (ikind, jkind, iatom, jatom, cell_b, &
244 : !$OMP iab, irow, icol, blocks_vr, blocks_rv, &
245 : !$OMP found, iac, ibc, alist_ac, alist_bc, &
246 : !$OMP na, np, nb, kkind, kac, kbc, i, lock_num, &
247 38 : !$OMP hash, natom, acint, bcint, achint, bchint)
248 :
249 : !$OMP SINGLE
250 : !$ ALLOCATE (locks(nlock))
251 : !$OMP END SINGLE
252 :
253 : !$OMP DO
254 : !$ DO lock_num = 1, nlock
255 : !$ call omp_init_lock(locks(lock_num))
256 : !$ END DO
257 : !$OMP END DO
258 :
259 : !$OMP DO SCHEDULE(GUIDED)
260 :
261 : DO slot = 1, sab_all(1)%nl_size
262 :
263 : ikind = sab_all(1)%nlist_task(slot)%ikind
264 : jkind = sab_all(1)%nlist_task(slot)%jkind
265 : iatom = sab_all(1)%nlist_task(slot)%iatom
266 : jatom = sab_all(1)%nlist_task(slot)%jatom
267 : cell_b(:) = sab_all(1)%nlist_task(slot)%cell(:)
268 :
269 : IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
270 : IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
271 : iab = ikind + nkind*(jkind - 1)
272 :
273 : ! *** Create matrix blocks for a new matrix block column ***
274 : irow = iatom
275 : icol = jatom
276 : DO i = 1, 3
277 : CALL dbcsr_get_block_p(matrix_vr(i)%matrix, irow, icol, blocks_vr(i)%block, found)
278 : CPASSERT(found)
279 : CALL dbcsr_get_block_p(matrix_rv(i)%matrix, irow, icol, blocks_rv(i)%block, found)
280 : CPASSERT(found)
281 : END DO
282 :
283 : ! loop over all kinds for projector atom
284 : DO kkind = 1, nkind
285 : iac = ikind + nkind*(kkind - 1)
286 : ibc = jkind + nkind*(kkind - 1)
287 : IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
288 : IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
289 : CALL get_alist(sap_int(iac), alist_ac, iatom)
290 : CALL get_alist(sap_int(ibc), alist_bc, jatom)
291 :
292 : IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
293 : IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
294 : DO kac = 1, alist_ac%nclist
295 : DO kbc = 1, alist_bc%nclist
296 : IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
297 : IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
298 : IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
299 : acint => alist_ac%clist(kac)%acint
300 : bcint => alist_bc%clist(kbc)%acint
301 : achint => alist_ac%clist(kac)%achint
302 : bchint => alist_bc%clist(kbc)%achint
303 : na = SIZE(acint, 1)
304 : np = SIZE(acint, 2)
305 : nb = SIZE(bcint, 1)
306 : !$ hash = MOD((iatom - 1)*natom + jatom, nlock) + 1
307 : !$ CALL omp_set_lock(locks(hash))
308 : DO i = 1, 3
309 : ! Vnl*r
310 : blocks_vr(i)%block(1:na, 1:nb) = blocks_vr(i)%block(1:na, 1:nb) + &
311 : MATMUL(achint(1:na, 1:np, 1), &
312 : TRANSPOSE(bcint(1:nb, 1:np, i + 1)))
313 : ! r*Vnl
314 : blocks_rv(i)%block(1:na, 1:nb) = blocks_rv(i)%block(1:na, 1:nb) + &
315 : MATMUL(achint(1:na, 1:np, i + 1), &
316 : TRANSPOSE(bcint(1:nb, 1:np, 1)))
317 : END DO
318 : !$ CALL omp_unset_lock(locks(hash))
319 : EXIT ! We have found a match and there can be only one single match
320 : END IF
321 : END DO
322 : END DO
323 : END DO
324 : DO i = 1, 3
325 : NULLIFY (blocks_vr(i)%block)
326 : NULLIFY (blocks_rv(i)%block)
327 : END DO
328 : END DO
329 :
330 : !$OMP DO
331 : !$ DO lock_num = 1, nlock
332 : !$ call omp_destroy_lock(locks(lock_num))
333 : !$ END DO
334 : !$OMP END DO
335 :
336 : !$OMP SINGLE
337 : !$ DEALLOCATE (locks)
338 : !$OMP END SINGLE NOWAIT
339 :
340 : !$OMP END PARALLEL
341 :
342 38 : CALL release_sap_int(sap_int)
343 :
344 38 : DEALLOCATE (basis_set)
345 :
346 38 : CALL timestop(handle)
347 :
348 114 : END SUBROUTINE build_rpnl_matrices
349 :
350 : ! **************************************************************************************************
351 : !> \brief Calculation of the product Tr or rT over Cartesian Gaussian functions.
352 : !> \param matrix_tr ...
353 : !> \param matrix_rt ...
354 : !> \param qs_env ...
355 : !> \param qs_kind_set ...
356 : !> \param basis_type basis set to be used
357 : !> \param sab_nl pair list (must be consistent with basis sets!)
358 : !> \param rc ...
359 : !> \date 11.10.2010
360 : !> \par History
361 : !> Ported from qs_overlap, replaces code in build_core_hamiltonian
362 : !> Refactoring [07.2014] JGH
363 : !> Simplify options and use new kinetic energy integral routine
364 : !> Adapted from qs_kinetic [07.2016]
365 : !> Adapted from the kinetic position-product recurrence [2021] by ED
366 : !> \author JGH
367 : !> \version 1.0
368 : ! **************************************************************************************************
369 38 : SUBROUTINE build_tr_matrices(matrix_tr, matrix_rt, qs_env, qs_kind_set, basis_type, sab_nl, rc)
370 :
371 : TYPE(dbcsr_p_type), DIMENSION(:) :: matrix_tr, matrix_rt
372 : TYPE(qs_environment_type), POINTER :: qs_env
373 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
374 : CHARACTER(LEN=*), INTENT(IN) :: basis_type
375 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
376 : POINTER :: sab_nl
377 : REAL(KIND=dp), DIMENSION(3) :: rc
378 :
379 : CHARACTER(len=*), PARAMETER :: routineN = 'build_tr_matrices'
380 :
381 : INTEGER :: handle, i, iatom, icol, ikind, ir, irow, &
382 : iset, jatom, jkind, jset, ldsab, ltab, &
383 : natom, ncoa, ncob, nkind, nseta, &
384 : nsetb, sgfa, sgfb, slot
385 : INTEGER, DIMENSION(3) :: cell
386 38 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, npgfa, &
387 38 : npgfb, nsgfa, nsgfb
388 38 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
389 : LOGICAL :: do_symmetric, found, trans
390 : REAL(KIND=dp) :: tab
391 38 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: qab, tkab
392 38 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: kab
393 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rac, rb, rbc
394 38 : REAL(KIND=dp), DIMENSION(:), POINTER :: set_radius_a, set_radius_b
395 38 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: rpgfa, rpgfb, scon_a, scon_b, zeta, zetb
396 342 : TYPE(block_p_type), DIMENSION(3, 2) :: blocks_tr
397 : TYPE(cell_type), POINTER :: qs_cell
398 38 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
399 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
400 38 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
401 :
402 : !$ INTEGER(kind=omp_lock_kind), &
403 38 : !$ ALLOCATABLE, DIMENSION(:) :: locks
404 : !$ INTEGER :: lock_num, hash, hash1, hash2
405 : !$ INTEGER(KIND=int_8) :: iatom8
406 : !$ INTEGER, PARAMETER :: nlock = 501
407 :
408 : MARK_USED(int_8)
409 :
410 38 : CALL timeset(routineN, handle)
411 :
412 38 : nkind = SIZE(qs_kind_set)
413 :
414 : ! check for symmetry
415 38 : CPASSERT(SIZE(sab_nl) > 0)
416 38 : CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
417 :
418 : ! prepare basis set
419 190 : ALLOCATE (basis_set_list(nkind))
420 38 : CALL basis_set_list_setup(basis_set_list, basis_type, qs_kind_set)
421 :
422 : ! *** Allocate work storage ***
423 38 : ldsab = get_memory_usage(qs_kind_set, basis_type)
424 :
425 : CALL get_qs_env(qs_env=qs_env, &
426 : particle_set=particle_set, &
427 : cell=qs_cell, &
428 38 : natom=natom)
429 :
430 : !$OMP PARALLEL DEFAULT(NONE) &
431 : !$OMP SHARED (ldsab,do_symmetric, sab_nl, rc,&
432 : !$OMP ncoset,matrix_tr,matrix_rt,basis_set_list,qs_cell,natom,locks) &
433 : !$OMP PRIVATE (blocks_tr,kab,qab,tab,ikind,jkind,iatom,jatom,rab,rac,rbc,cell, &
434 : !$OMP basis_set_a, basis_set_b, nseta, ncoa, ncob, ltab, nsetb, tkab, &
435 : !$OMP irow, icol, found, trans, sgfa, sgfb, iset, jset, i, &
436 : !$OMP hash, hash1, hash2, iatom8, slot, lock_num) &
437 : !$OMP PRIVATE (first_sgfa, la_max, la_min, npgfa, nsgfa, rpgfa, set_radius_a, zeta, scon_a) &
438 : !$OMP PRIVATE (first_sgfb, lb_max, lb_min, npgfb, nsgfb, rpgfb, set_radius_b, zetb, scon_b) &
439 : !$OMP SHARED(particle_set) &
440 38 : !$OMP PRIVATE(ra, rb)
441 :
442 : !$OMP SINGLE
443 : !$ ALLOCATE (locks(nlock))
444 : !$OMP END SINGLE
445 :
446 : !$OMP DO
447 : !$ DO lock_num = 1, nlock
448 : !$ call omp_init_lock(locks(lock_num))
449 : !$ END DO
450 : !$OMP END DO
451 :
452 : ALLOCATE (kab(ldsab, ldsab, 3), qab(ldsab, ldsab))
453 :
454 : !$OMP DO SCHEDULE(GUIDED)
455 : DO slot = 1, sab_nl(1)%nl_size
456 :
457 : ikind = sab_nl(1)%nlist_task(slot)%ikind
458 : jkind = sab_nl(1)%nlist_task(slot)%jkind
459 : iatom = sab_nl(1)%nlist_task(slot)%iatom
460 : jatom = sab_nl(1)%nlist_task(slot)%jatom
461 : cell(:) = sab_nl(1)%nlist_task(slot)%cell(:)
462 : rab(1:3) = sab_nl(1)%nlist_task(slot)%r(1:3)
463 :
464 : basis_set_a => basis_set_list(ikind)%gto_basis_set
465 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
466 : basis_set_b => basis_set_list(jkind)%gto_basis_set
467 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
468 :
469 : !$ iatom8 = INT(iatom - 1, int_8)*INT(natom, int_8) + INT(jatom, int_8)
470 : !$ hash1 = INT(MOD(iatom8, INT(nlock, int_8)) + 1)
471 :
472 : ! basis ikind
473 : first_sgfa => basis_set_a%first_sgf
474 : la_max => basis_set_a%lmax
475 : la_min => basis_set_a%lmin
476 : npgfa => basis_set_a%npgf
477 : nsgfa => basis_set_a%nsgf_set
478 : rpgfa => basis_set_a%pgf_radius
479 : set_radius_a => basis_set_a%set_radius
480 : scon_a => basis_set_a%scon
481 : zeta => basis_set_a%zet
482 : ! basis jkind
483 : first_sgfb => basis_set_b%first_sgf
484 : lb_max => basis_set_b%lmax
485 : lb_min => basis_set_b%lmin
486 : npgfb => basis_set_b%npgf
487 : nsgfb => basis_set_b%nsgf_set
488 : rpgfb => basis_set_b%pgf_radius
489 : set_radius_b => basis_set_b%set_radius
490 : scon_b => basis_set_b%scon
491 : zetb => basis_set_b%zet
492 :
493 : nseta = basis_set_a%nset
494 : nsetb = basis_set_b%nset
495 :
496 : IF (do_symmetric) THEN
497 : IF (iatom <= jatom) THEN
498 : irow = iatom
499 : icol = jatom
500 : ELSE
501 : irow = jatom
502 : icol = iatom
503 : END IF
504 : ELSE
505 : irow = iatom
506 : icol = jatom
507 : END IF
508 : DO ir = 1, 3
509 : NULLIFY (blocks_tr(ir, 1)%block)
510 : CALL dbcsr_get_block_p(matrix=matrix_tr(ir)%matrix, &
511 : row=irow, col=icol, BLOCK=blocks_tr(ir, 1)%block, found=found)
512 : CPASSERT(found)
513 : NULLIFY (blocks_tr(ir, 2)%block)
514 : CALL dbcsr_get_block_p(matrix=matrix_rt(ir)%matrix, &
515 : row=irow, col=icol, BLOCK=blocks_tr(ir, 2)%block, found=found)
516 : CPASSERT(found)
517 : END DO
518 :
519 : ! The kinetic integrals depend only on rab (also for the screening)
520 : tab = NORM2(rab)
521 :
522 : ! With and without MIC, rab(:) is the vector giving us the coordinates of rb.
523 : ra = pbc(particle_set(iatom)%r(:), qs_cell)
524 : rb(:) = ra(:) + rab(:)
525 : rac = pbc(rc, ra, qs_cell)
526 : rbc = rac + rab
527 :
528 : trans = do_symmetric .AND. (iatom > jatom)
529 :
530 : DO iset = 1, nseta
531 :
532 : ncoa = npgfa(iset)*(ncoset(la_max(iset)) - ncoset(la_min(iset) - 1))
533 : sgfa = first_sgfa(1, iset)
534 :
535 : DO jset = 1, nsetb
536 :
537 : IF (set_radius_a(iset) + set_radius_b(jset) < tab) CYCLE
538 :
539 : !$ hash2 = MOD((iset - 1)*nsetb + jset, nlock) + 1
540 : !$ hash = MOD(hash1 + hash2, nlock) + 1
541 :
542 : ncob = npgfb(jset)*(ncoset(lb_max(jset)) - ncoset(lb_min(jset) - 1))
543 : sgfb = first_sgfb(1, jset)
544 :
545 : ! calculate integrals
546 : ltab = MAX(npgfa(iset)*ncoset(la_max(iset) + 1), npgfb(jset)*ncoset(lb_max(jset) + 1))
547 : ALLOCATE (tkab(ltab, ltab))
548 : CALL kinetic(la_max(iset) + 1, la_min(iset), npgfa(iset), rpgfa(:, iset), zeta(:, iset), &
549 : lb_max(jset) + 1, lb_min(jset), npgfb(jset), rpgfb(:, jset), zetb(:, jset), &
550 : rab, tkab)
551 : ! Ordered products T*r and r*T
552 : DO i = 1, 2
553 : CALL ab_opr(la_max(iset), npgfa(iset), rpgfa(:, iset), la_min(iset), &
554 : lb_max(jset), npgfb(jset), rpgfb(:, jset), lb_min(jset), &
555 : tab, tkab, kab, rac, rbc, direction_Or=(i == 1))
556 : DO ir = 1, 3
557 : CALL contraction(kab(:, :, ir), qab, ca=scon_a(:, sgfa:), na=ncoa, ma=nsgfa(iset), &
558 : cb=scon_b(:, sgfb:), nb=ncob, mb=nsgfb(jset), trans=trans)
559 :
560 : !$ CALL omp_set_lock(locks(hash))
561 : CALL block_add("IN", qab, nsgfa(iset), nsgfb(jset), blocks_tr(ir, i)%block, &
562 : sgfa, sgfb, trans=trans)
563 : !$ CALL omp_unset_lock(locks(hash))
564 : END DO
565 : END DO
566 : DEALLOCATE (tkab)
567 :
568 : END DO
569 : END DO
570 : END DO !iterator
571 : DEALLOCATE (kab, qab)
572 : !$OMP DO
573 : !$ DO lock_num = 1, nlock
574 : !$ call omp_destroy_lock(locks(lock_num))
575 : !$ END DO
576 : !$OMP END DO
577 :
578 : !$OMP SINGLE
579 : !$ DEALLOCATE (locks)
580 : !$OMP END SINGLE NOWAIT
581 :
582 : !$OMP END PARALLEL
583 :
584 : ! Release work storage
585 38 : DEALLOCATE (basis_set_list)
586 38 : CALL timestop(handle)
587 :
588 152 : END SUBROUTINE build_tr_matrices
589 :
590 : ! **************************************************************************************************
591 : !> \brief Build the ordered products V_core*r and r*V_core.
592 : !> \param matrix_rcore_hr ...
593 : !> \param matrix_rcore_rh ...
594 : !> \param qs_env ...
595 : !> \param qs_kind_set ...
596 : !> \param basis_type ...
597 : !> \param sab_nl ...
598 : !> \param rf ...
599 : !> \author Edward Ditler, Tomas Zimmermann
600 : ! **************************************************************************************************
601 38 : SUBROUTINE build_rcore_matrices(matrix_rcore_hr, matrix_rcore_rh, qs_env, qs_kind_set, basis_type, sab_nl, rf)
602 : TYPE(dbcsr_p_type), DIMENSION(:) :: matrix_rcore_hr, matrix_rcore_rh
603 : TYPE(qs_environment_type), POINTER :: qs_env
604 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
605 : CHARACTER(LEN=*) :: basis_type
606 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
607 : POINTER :: sab_nl
608 : REAL(KIND=dp), DIMENSION(3) :: rf
609 :
610 : CHARACTER(len=*), PARAMETER :: routineN = 'build_rcore_matrices'
611 : INTEGER, PARAMETER :: nexp_max = 30
612 :
613 : INTEGER :: atom_a, atom_b, handle, i, iatom, icol, idir, ikind, inode, irow, iset, jatom, &
614 : jkind, jset, katom, kkind, ldai, ldsab, maxco, maxder, maxl, maxlgto, maxlppl, maxnset, &
615 : maxsgf, mepos, n_local, ncoa, ncob, nder, nexp_lpot, nexp_ppl, nimages, nkind, nloc, &
616 : nseta, nsetb, nthread, sgfa, sgfb
617 38 : INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind
618 : INTEGER, DIMENSION(1:10) :: nrloc
619 : INTEGER, DIMENSION(3) :: cellind
620 38 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, &
621 38 : nct_lpot, npgfa, npgfb, nsgfa, nsgfb
622 38 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
623 : INTEGER, DIMENSION(nexp_max) :: nct_ppl
624 : LOGICAL :: do_symmetric, dokp, ecp_local, &
625 : ecp_semi_local, found, lpotextended
626 : REAL(KIND=dp) :: alpha, dab, dac, dbc, ppl_radius
627 38 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: hab, qab
628 38 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: ppl_work, rhab, work
629 : REAL(KIND=dp), DIMENSION(1:10) :: aloc, bloc
630 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rac, raf, rb, rbc, rbf
631 : REAL(KIND=dp), DIMENSION(4, nexp_max) :: cval_ppl
632 76 : REAL(KIND=dp), DIMENSION(:), POINTER :: a_local, alpha_lpot, c_local, cexp_ppl, &
633 38 : set_radius_a, set_radius_b
634 38 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: cval_lpot, rpgfa, rpgfb, scon_a, scon_b, &
635 38 : sphi_a, sphi_b, zeta, zetb
636 : REAL(KIND=dp), DIMENSION(nexp_max) :: alpha_ppl
637 38 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
638 342 : TYPE(block_p_type), DIMENSION(3, 2) :: blocks_rcore
639 : TYPE(cell_type), POINTER :: cell
640 : TYPE(gth_potential_type), POINTER :: gth_potential
641 38 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
642 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
643 : TYPE(neighbor_list_iterator_p_type), &
644 76 : DIMENSION(:), POINTER :: ap_iterator, nl_iterator
645 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
646 38 : POINTER :: sac_ppl
647 38 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
648 : TYPE(sgp_potential_type), POINTER :: sgp_potential
649 :
650 38 : CALL timeset(routineN, handle)
651 :
652 : CALL get_qs_env(qs_env=qs_env, &
653 : atomic_kind_set=atomic_kind_set, &
654 : qs_kind_set=qs_kind_set, &
655 : particle_set=particle_set, &
656 : sac_ppl=sac_ppl, &
657 38 : cell=cell)
658 :
659 : ! check for symmetry
660 38 : CPASSERT(SIZE(sab_nl) > 0)
661 38 : CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
662 :
663 38 : nkind = SIZE(qs_kind_set)
664 :
665 : ! prepare basis set
666 190 : ALLOCATE (basis_set_list(nkind))
667 38 : CALL basis_set_list_setup(basis_set_list, basis_type, qs_kind_set)
668 :
669 38 : nder = 0
670 38 : nimages = 1
671 :
672 : alpha_ppl = 0
673 : nct_ppl = 0
674 : cval_ppl = 0
675 :
676 38 : nkind = SIZE(atomic_kind_set)
677 :
678 38 : dokp = (nimages > 1)
679 :
680 38 : CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, atom_of_kind=atom_of_kind)
681 :
682 38 : maxder = ncoset(nder)
683 :
684 : CALL get_qs_kind_set(qs_kind_set, maxco=maxco, maxlgto=maxlgto, &
685 : maxsgf=maxsgf, maxnset=maxnset, maxlppl=maxlppl, &
686 38 : basis_type=basis_type)
687 :
688 38 : maxl = MAX(maxlgto, maxlppl)
689 38 : CALL init_orbital_pointers(2*maxl + 2*nder + 2)
690 :
691 : !tz: maxco in maxco*ncoset(maxlgto+1) is an overkill,
692 : ! properly there should be maxpgf*ncoset(maxlgto+1), but maxpgf is difficult to get
693 38 : ldsab = MAX(maxco, ncoset(maxlppl), maxsgf, maxlppl, maxco*ncoset(maxlgto + 1))
694 38 : ldai = ncoset(2*maxlgto + 2)
695 :
696 114 : DO ikind = 1, nkind
697 76 : CALL get_qs_kind(qs_kind_set(ikind), basis_set=basis_set_a, basis_type=basis_type)
698 114 : IF (ASSOCIATED(basis_set_a)) THEN
699 76 : basis_set_list(ikind)%gto_basis_set => basis_set_a
700 : ELSE
701 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
702 : END IF
703 : END DO
704 :
705 : nthread = 1
706 38 : !$ nthread = omp_get_max_threads()
707 :
708 38 : CALL neighbor_list_iterator_create(nl_iterator, sab_nl, nthread=nthread)
709 :
710 : ! iterator for basis/potential list
711 38 : CALL neighbor_list_iterator_create(ap_iterator, sac_ppl, search=.TRUE., nthread=nthread)
712 :
713 : !$OMP PARALLEL &
714 : !$OMP DEFAULT (NONE) &
715 : !$OMP SHARED (nl_iterator, ap_iterator, basis_set_list, &
716 : !$OMP atomic_kind_set, qs_kind_set, particle_set, &
717 : !$OMP sab_nl, sac_ppl, nthread, ncoset, nkind, &
718 : !$OMP atom_of_kind, ldsab, maxnset, maxder, &
719 : !$OMP maxlgto, nder, maxco, dokp, cell) &
720 : !$OMP SHARED (matrix_rcore_hr, matrix_rcore_rh, rf) &
721 : !$OMP PRIVATE (ikind, jkind, inode, iatom, jatom, rab, basis_set_a, basis_set_b, atom_a) &
722 : !$OMP PRIVATE (atom_b) &
723 : !$OMP PRIVATE (nsetb) &
724 : !$OMP PRIVATE (dab, irow, icol, blocks_rcore, found, iset, ncoa, i) &
725 : !$OMP PRIVATE (sgfa, jset, ncob, sgfb, work, hab, rhab, kkind, nseta) &
726 : !$OMP PRIVATE (gth_potential, sgp_potential, alpha, cexp_ppl, lpotextended) &
727 : !$OMP PRIVATE (ppl_radius, nexp_lpot, nexp_ppl, alpha_ppl, alpha_lpot, nct_ppl) &
728 : !$OMP PRIVATE (ecp_semi_local, nct_lpot, cval_ppl, cval_lpot, rac, dac, rbc, dbc) &
729 : !$OMP PRIVATE (mepos) &
730 : !$OMP PRIVATE (katom, ppl_work, cellind, ecp_local) &
731 : !$OMP PRIVATE (first_sgfa, la_max, la_min, npgfa, nsgfa, rpgfa, set_radius_a, sphi_a, zeta, scon_a) &
732 : !$OMP PRIVATE (first_sgfb, lb_max, lb_min, npgfb, nsgfb, rpgfb, set_radius_b, sphi_b, zetb, scon_b) &
733 : !$OMP PRIVATE (nloc, nrloc, aloc, bloc, n_local, a_local, c_local, ldai) &
734 38 : !$OMP PRIVATE (ra, rb, qab, raf, rbf)
735 :
736 : mepos = 0
737 : !$ mepos = omp_get_thread_num()
738 :
739 : ALLOCATE (hab(ldsab, ldsab), rhab(ldsab, ldsab, 3), work(ldsab, ldsab*(nder + 1), 3))
740 : ALLOCATE (qab(ldsab, ldsab))
741 :
742 : ldai = ncoset(2*maxlgto + 2)
743 : ALLOCATE (ppl_work(ldai, ldai, MAX(maxder, 2*maxlgto + 2 + 1)))
744 :
745 : DO WHILE (neighbor_list_iterate(nl_iterator, mepos=mepos) == 0)
746 :
747 : CALL get_iterator_info(nl_iterator, mepos=mepos, ikind=ikind, jkind=jkind, inode=inode, &
748 : iatom=iatom, jatom=jatom, r=rab, cell=cellind)
749 :
750 : basis_set_a => basis_set_list(ikind)%gto_basis_set
751 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
752 : basis_set_b => basis_set_list(jkind)%gto_basis_set
753 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
754 :
755 : atom_a = atom_of_kind(iatom)
756 : atom_b = atom_of_kind(jatom)
757 :
758 : ! basis ikind
759 : first_sgfa => basis_set_a%first_sgf
760 : la_max => basis_set_a%lmax
761 : la_min => basis_set_a%lmin
762 : npgfa => basis_set_a%npgf
763 : nsgfa => basis_set_a%nsgf_set
764 : rpgfa => basis_set_a%pgf_radius
765 : set_radius_a => basis_set_a%set_radius
766 : sphi_a => basis_set_a%sphi
767 : zeta => basis_set_a%zet
768 : scon_a => basis_set_a%scon
769 : ! basis jkind
770 : first_sgfb => basis_set_b%first_sgf
771 : lb_max => basis_set_b%lmax
772 : lb_min => basis_set_b%lmin
773 : npgfb => basis_set_b%npgf
774 : nsgfb => basis_set_b%nsgf_set
775 : rpgfb => basis_set_b%pgf_radius
776 : set_radius_b => basis_set_b%set_radius
777 : sphi_b => basis_set_b%sphi
778 : zetb => basis_set_b%zet
779 : scon_b => basis_set_b%scon
780 :
781 : nseta = basis_set_a%nset
782 : nsetb = basis_set_b%nset
783 :
784 : ! *** Create matrix blocks for a new matrix block column ***
785 : irow = iatom
786 : icol = jatom
787 :
788 : DO idir = 1, 3
789 : NULLIFY (blocks_rcore(idir, 1)%block)
790 : CALL dbcsr_get_block_p(matrix=matrix_rcore_hr(idir)%matrix, &
791 : row=irow, col=icol, BLOCK=blocks_rcore(idir, 1)%block, found=found)
792 : CPASSERT(found)
793 : NULLIFY (blocks_rcore(idir, 2)%block)
794 : CALL dbcsr_get_block_p(matrix=matrix_rcore_rh(idir)%matrix, &
795 : row=irow, col=icol, BLOCK=blocks_rcore(idir, 2)%block, found=found)
796 : CPASSERT(found)
797 : END DO
798 :
799 : dab = NORM2(rab)
800 : ra = pbc(particle_set(iatom)%r(:), cell)
801 : rb(:) = ra(:) + rab(:)
802 :
803 : raf = pbc(rf, ra, cell)
804 : rbf = raf + rab
805 :
806 : ! loop over all kinds for pseudopotential atoms
807 : DO kkind = 1, nkind
808 : CALL get_qs_kind(qs_kind_set(kkind), gth_potential=gth_potential, &
809 : sgp_potential=sgp_potential)
810 : IF (ASSOCIATED(gth_potential)) THEN
811 : CALL get_potential(potential=gth_potential, &
812 : alpha_ppl=alpha, cexp_ppl=cexp_ppl, &
813 : lpot_present=lpotextended, ppl_radius=ppl_radius)
814 : nexp_ppl = 1
815 : alpha_ppl(1) = alpha
816 : nct_ppl(1) = SIZE(cexp_ppl)
817 : cval_ppl(1:nct_ppl(1), 1) = cexp_ppl(1:nct_ppl(1))
818 : IF (lpotextended) THEN
819 : CALL get_potential(potential=gth_potential, &
820 : nexp_lpot=nexp_lpot, alpha_lpot=alpha_lpot, nct_lpot=nct_lpot, cval_lpot=cval_lpot)
821 : CPASSERT(nexp_lpot < nexp_max)
822 : nexp_ppl = nexp_lpot + 1
823 : alpha_ppl(2:nexp_lpot + 1) = alpha_lpot(1:nexp_lpot)
824 : nct_ppl(2:nexp_lpot + 1) = nct_lpot(1:nexp_lpot)
825 : DO i = 1, nexp_lpot
826 : cval_ppl(1:nct_lpot(i), i + 1) = cval_lpot(1:nct_lpot(i), i)
827 : END DO
828 : END IF
829 : ELSE IF (ASSOCIATED(sgp_potential)) THEN
830 : CALL get_potential(potential=sgp_potential, ecp_local=ecp_local, ecp_semi_local=ecp_semi_local, &
831 : ppl_radius=ppl_radius)
832 : IF (ecp_local) THEN
833 : CALL get_potential(potential=sgp_potential, nloc=nloc, nrloc=nrloc, aloc=aloc, bloc=bloc)
834 : IF (SUM(ABS(aloc(1:nloc))) < 1.0e-12_dp) CYCLE
835 : nexp_ppl = nloc
836 : CPASSERT(nexp_ppl <= nexp_max)
837 : nct_ppl(1:nloc) = nrloc(1:nloc) - 1
838 : alpha_ppl(1:nloc) = bloc(1:nloc)
839 : cval_ppl(1, 1:nloc) = aloc(1:nloc)
840 : ELSE
841 : CALL get_potential(potential=sgp_potential, n_local=n_local, a_local=a_local, c_local=c_local)
842 : nexp_ppl = n_local
843 : CPASSERT(nexp_ppl <= nexp_max)
844 : nct_ppl(1:n_local) = 1
845 : alpha_ppl(1:n_local) = a_local(1:n_local)
846 : cval_ppl(1, 1:n_local) = c_local(1:n_local)
847 : END IF
848 : IF (ecp_semi_local) THEN
849 : CPABORT("VCD with semi-local ECPs not implemented")
850 : END IF
851 : ELSE
852 : CYCLE
853 : END IF
854 :
855 : CALL nl_set_sub_iterator(ap_iterator, ikind, kkind, iatom, mepos=mepos)
856 :
857 : DO WHILE (nl_sub_iterate(ap_iterator, mepos=mepos) == 0)
858 :
859 : CALL get_iterator_info(ap_iterator, mepos=mepos, jatom=katom, r=rac)
860 : dac = SQRT(SUM(rac*rac))
861 : rbc(:) = rac(:) - rab(:)
862 : dbc = SQRT(SUM(rbc*rbc))
863 : IF ((MAXVAL(set_radius_a(:)) + ppl_radius < dac) .OR. &
864 : (MAXVAL(set_radius_b(:)) + ppl_radius < dbc)) THEN
865 : CYCLE
866 : END IF
867 : DO iset = 1, nseta
868 : IF (set_radius_a(iset) + ppl_radius < dac) CYCLE
869 : ncoa = npgfa(iset)*ncoset(la_max(iset))
870 : ! ncoa = npgfa(iset)*(ncoset(la_max(iset))-ncoset(la_min(iset)-1))
871 : sgfa = first_sgfa(1, iset)
872 : DO jset = 1, nsetb
873 : IF (set_radius_b(jset) + ppl_radius < dbc) CYCLE
874 : ncob = npgfb(jset)*ncoset(lb_max(jset))
875 : ! ncob = npgfb(jset)*(ncoset(lb_max(jset))-ncoset(lb_min(jset)-1))
876 : sgfb = first_sgfb(1, jset)
877 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
878 : ! *** Calculate the GTH pseudo potential forces ***
879 : hab = 0
880 : rhab = 0
881 : ppl_work = 0
882 : work = 0
883 :
884 : CALL ppl_integral( &
885 : la_max(iset) + 1, la_min(iset), npgfa(iset), &
886 : rpgfa(:, iset), zeta(:, iset), &
887 : lb_max(jset) + 1, lb_min(jset), npgfb(jset), &
888 : rpgfb(:, jset), zetb(:, jset), &
889 : nexp_ppl, alpha_ppl, nct_ppl, cval_ppl, ppl_radius, &
890 : rab, dab, rac, dac, rbc, dbc, hab(:, :), ppl_work)
891 :
892 : ! product with r
893 : CALL ab_opr(la_max(iset), npgfa(iset), rpgfa(:, iset), 0, &
894 : lb_max(jset), npgfb(jset), rpgfb(:, jset), 0, &
895 : dab, hab(:, :), rhab(:, :, :), raf, rbf, &
896 : direction_Or=.FALSE.)
897 :
898 : DO idir = 1, 3
899 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
900 : 1.0_dp, rhab(1, 1, idir), SIZE(rhab, 1), &
901 : sphi_b(1, sgfb), SIZE(sphi_b, 1), &
902 : 0.0_dp, work(1, 1, idir), SIZE(work, 1))
903 : !$OMP CRITICAL(h_block_critical)
904 : DO i = 1, 2
905 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
906 : 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
907 : work(1, 1, idir), SIZE(work, 1), &
908 : 1.0_dp, blocks_rcore(idir, i)%block(sgfa, sgfb), &
909 : SIZE(blocks_rcore(idir, i)%block, 1))
910 : END DO
911 : !$OMP END CRITICAL(h_block_critical)
912 : END DO
913 : END DO
914 : END DO
915 : END DO
916 : END DO
917 : END DO ! iterator
918 :
919 : DEALLOCATE (hab, rhab, work, ppl_work)
920 :
921 : !$OMP END PARALLEL
922 :
923 38 : CALL neighbor_list_iterator_release(ap_iterator)
924 38 : CALL neighbor_list_iterator_release(nl_iterator)
925 :
926 38 : DEALLOCATE (atom_of_kind, basis_set_list)
927 :
928 38 : CALL timestop(handle)
929 :
930 190 : END SUBROUTINE build_rcore_matrices
931 :
932 : ! **************************************************************************************************
933 : !> \brief Build the ordered Hartree+XC products V_HXC*r and r*V_HXC.
934 : !> \param matrix_hr ...
935 : !> \param matrix_rh ...
936 : !> \param qs_env ...
937 : !> \param rc ...
938 : !> \author Edward Ditler, Tomas Zimmermann
939 : ! **************************************************************************************************
940 38 : SUBROUTINE build_vhxc_matrices(matrix_hr, matrix_rh, qs_env, rc)
941 : TYPE(dbcsr_p_type), DIMENSION(:, :), &
942 : INTENT(INOUT), POINTER :: matrix_hr, matrix_rh
943 : TYPE(qs_environment_type), POINTER :: qs_env
944 : REAL(KIND=dp), DIMENSION(3) :: rc
945 :
946 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_vhxc_matrices'
947 : INTEGER, PARAMETER :: nspins = 1
948 :
949 : INTEGER :: handle, idir, ispin
950 : REAL(kind=dp) :: edisp
951 38 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks
952 38 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_rvxc, matrix_rvxc_desymm
953 : TYPE(pw_env_type), POINTER :: pw_env
954 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
955 38 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_rspace, v_tau_rspace
956 : TYPE(pw_r3d_rs_type), POINTER :: v_hartree_rspace
957 : TYPE(qs_energy_type), POINTER :: energy
958 : TYPE(qs_ks_env_type), POINTER :: ks_env
959 : TYPE(qs_rho_type), POINTER :: rho_struct
960 : TYPE(section_vals_type), POINTER :: input, xc_section
961 :
962 38 : CALL timeset(routineN, handle)
963 :
964 : CALL get_qs_env(qs_env, matrix_ks=matrix_ks, &
965 : ks_env=ks_env, &
966 : pw_env=pw_env, &
967 : input=input, &
968 : v_hartree_rspace=v_hartree_rspace, &
969 38 : energy=energy)
970 :
971 38 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
972 :
973 38 : NULLIFY (matrix_rvxc, matrix_rvxc_desymm)
974 38 : CALL dbcsr_allocate_matrix_set(matrix_rvxc, nspins, 3)
975 38 : CALL dbcsr_allocate_matrix_set(matrix_rvxc_desymm, nspins, 3)
976 :
977 76 : DO ispin = 1, nspins
978 190 : DO idir = 1, 3
979 114 : CALL dbcsr_init_p(matrix_rvxc(ispin, idir)%matrix)
980 114 : CALL dbcsr_init_p(matrix_rvxc_desymm(ispin, idir)%matrix)
981 :
982 114 : CALL dbcsr_copy(matrix_rvxc_desymm(ispin, idir)%matrix, matrix_hr(1, 1)%matrix)
983 114 : CALL dbcsr_set(matrix_rvxc_desymm(ispin, idir)%matrix, 0._dp)
984 :
985 114 : CALL dbcsr_copy(matrix_rvxc(ispin, idir)%matrix, matrix_ks(ispin)%matrix)
986 152 : CALL dbcsr_set(matrix_rvxc(ispin, idir)%matrix, 0.0_dp)
987 : END DO
988 : END DO
989 :
990 38 : xc_section => section_vals_get_subs_vals(input, "DFT%XC")
991 38 : CALL get_qs_env(qs_env=qs_env, rho=rho_struct)
992 :
993 38 : NULLIFY (v_rspace)
994 38 : NULLIFY (v_tau_rspace)
995 : CALL qs_vxc_create(ks_env=ks_env, rho_struct=rho_struct, xc_section=xc_section, &
996 : vxc_rho=v_rspace, vxc_tau=v_tau_rspace, exc=energy%exc, &
997 : edisp=edisp, dispersion_env=qs_env%dispersion_env, &
998 38 : just_energy=.FALSE.)
999 :
1000 38 : IF (.NOT. ASSOCIATED(v_rspace)) THEN
1001 0 : ALLOCATE (v_rspace(nspins))
1002 0 : DO ispin = 1, nspins
1003 0 : CALL auxbas_pw_pool%create_pw(v_rspace(ispin))
1004 0 : CALL pw_zero(v_rspace(ispin))
1005 : END DO
1006 : END IF
1007 :
1008 76 : DO ispin = 1, nspins
1009 38 : CALL pw_axpy(v_hartree_rspace, v_rspace(ispin), 1.0_dp/v_hartree_rspace%pw_grid%dvol)
1010 : CALL integrate_rv_rspace(v_rspace=v_rspace(ispin), hmat=matrix_rvxc(ispin, :), qs_env=qs_env, &
1011 38 : rc=rc)
1012 :
1013 190 : DO idir = 1, 3
1014 114 : CALL dbcsr_scale(matrix_rvxc(ispin, idir)%matrix, v_rspace(ispin)%pw_grid%dvol)
1015 114 : CALL dbcsr_desymmetrize(matrix_rvxc(ispin, idir)%matrix, matrix_rvxc_desymm(ispin, idir)%matrix)
1016 114 : CALL dbcsr_add(matrix_hr(ispin, idir)%matrix, matrix_rvxc_desymm(ispin, idir)%matrix, 1.0_dp, 1.0_dp)
1017 152 : CALL dbcsr_add(matrix_rh(ispin, idir)%matrix, matrix_rvxc_desymm(ispin, idir)%matrix, 1.0_dp, 1.0_dp)
1018 : END DO
1019 : END DO
1020 :
1021 : ! return pw grids
1022 76 : DO ispin = 1, nspins
1023 76 : CALL auxbas_pw_pool%give_back_pw(v_rspace(ispin))
1024 : END DO
1025 38 : DEALLOCATE (v_rspace)
1026 :
1027 38 : CALL dbcsr_deallocate_matrix_set(matrix_rvxc)
1028 38 : CALL dbcsr_deallocate_matrix_set(matrix_rvxc_desymm)
1029 :
1030 38 : CALL timestop(handle)
1031 :
1032 38 : END SUBROUTINE build_vhxc_matrices
1033 :
1034 : ! **************************************************************************************************
1035 : !> \brief Calculates the integrals < mu | r * V | nu >
1036 : !> There is no direction_Or argument, because the potentials commute with r
1037 : !> This routine uses integrate_pgf_product directly. It could probably be rewritten to use
1038 : !> the new task_list interface.
1039 : !> \param v_rspace ...
1040 : !> \param hmat ...
1041 : !> \param qs_env ...
1042 : !> \param rc ...
1043 : !> \author Edward Ditler
1044 : ! **************************************************************************************************
1045 38 : SUBROUTINE integrate_rv_rspace(v_rspace, hmat, qs_env, rc)
1046 :
1047 : TYPE(pw_r3d_rs_type) :: v_rspace
1048 : TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT) :: hmat
1049 : TYPE(qs_environment_type), POINTER :: qs_env
1050 : REAL(KIND=dp), DIMENSION(3) :: rc
1051 :
1052 : CHARACTER(len=*), PARAMETER :: routineN = 'integrate_rv_rspace'
1053 :
1054 : CHARACTER(len=default_string_length) :: my_basis_type
1055 : INTEGER :: bcol, brow, handle, iatom, idir, igrid_level, ikind, ikind_old, ilevel, img, &
1056 : ipair, ipgf, ipgf_new, iset, iset_new, iset_old, itask, ithread, jatom, jkind, jkind_old, &
1057 : jpgf, jpgf_new, jset, jset_new, jset_old, ldsab, maxco, maxlgto, maxpgf, maxset, &
1058 : maxsgf_set, na1, na2, natom, nb1, nb2, ncoa, ncoa_full, ncob, ncob_full, nkind, nseta, &
1059 : nsetb, nthread, sgfa, sgfb
1060 38 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, npgfa, &
1061 38 : npgfb, nsgfa, nsgfb
1062 38 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
1063 : LOGICAL :: atom_pair_changed, atom_pair_done, distributed_grids, found, has_threads, &
1064 : my_compute_tau, my_gapw, new_set_pair_coming
1065 : REAL(KIND=dp) :: dab, eps_rho_rspace, f, prefactor, &
1066 : radius, zetp
1067 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rab_inv, rac, rb, rbc, rp
1068 38 : REAL(KIND=dp), DIMENSION(:), POINTER :: set_radius_a, set_radius_b
1069 38 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: hab, rpgfa, rpgfb, sphi_a, sphi_b, work, &
1070 38 : zeta, zetb
1071 38 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: habt, rhab, workt
1072 38 : TYPE(atom_pair_type), DIMENSION(:), POINTER :: atom_pair_recv, atom_pair_send
1073 38 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1074 38 : TYPE(block_p_type), ALLOCATABLE, DIMENSION(:) :: h_block
1075 : TYPE(cell_type), POINTER :: cell
1076 : TYPE(dbcsr_distribution_type) :: dist
1077 : TYPE(dft_control_type), POINTER :: dft_control
1078 : TYPE(gridlevel_info_type), POINTER :: gridlevel_info
1079 : TYPE(gto_basis_set_type), POINTER :: orb_basis_set
1080 : TYPE(mp_comm_type) :: group
1081 38 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1082 : TYPE(pw_env_type), POINTER :: pw_env
1083 38 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1084 38 : TYPE(realspace_grid_type), DIMENSION(:), POINTER :: rs_v
1085 : TYPE(task_list_type), POINTER :: task_list, task_list_soft
1086 38 : TYPE(task_type), DIMENSION(:), POINTER :: tasks
1087 : TYPE(virial_type), POINTER :: virial
1088 :
1089 38 : CALL timeset(routineN, handle)
1090 :
1091 38 : my_compute_tau = .FALSE.
1092 38 : my_gapw = .FALSE.
1093 38 : my_basis_type = "ORB"
1094 :
1095 : ! get the task lists
1096 : CALL get_qs_env(qs_env=qs_env, &
1097 : task_list=task_list, &
1098 38 : task_list_soft=task_list_soft)
1099 38 : CPASSERT(ASSOCIATED(task_list))
1100 :
1101 : ! the information on the grids is provided through pw_env
1102 : ! pw_env has to be the parent env for the potential grid (input)
1103 : ! there is an option to provide an external grid
1104 38 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
1105 38 : CPASSERT(ASSOCIATED(pw_env))
1106 :
1107 : ! get all the general information on the system we are working on
1108 : CALL get_qs_env(qs_env=qs_env, &
1109 : atomic_kind_set=atomic_kind_set, &
1110 : qs_kind_set=qs_kind_set, &
1111 : cell=cell, &
1112 : dft_control=dft_control, &
1113 : particle_set=particle_set, &
1114 : virial=virial, &
1115 38 : natom=natom)
1116 :
1117 38 : rab = 0._dp
1118 38 : rac = 0._dp
1119 38 : rbc = 0._dp
1120 :
1121 : ! short cuts to task list variables
1122 38 : tasks => task_list%tasks
1123 38 : atom_pair_send => task_list%atom_pair_send
1124 38 : atom_pair_recv => task_list%atom_pair_recv
1125 :
1126 38 : CPASSERT(ASSOCIATED(pw_env))
1127 38 : CALL pw_env_get(pw_env, rs_grids=rs_v)
1128 :
1129 : ! get mpi group from rs_v
1130 38 : group = rs_v(1)%desc%group
1131 :
1132 : ! assign from pw_env
1133 38 : gridlevel_info => pw_env%gridlevel_info
1134 :
1135 : ! transform the potential on the rs_multigrids
1136 38 : CALL potential_pw2rs(rs_v, v_rspace, pw_env)
1137 :
1138 38 : nkind = SIZE(qs_kind_set)
1139 :
1140 : ! needs to be consistent with rho_rspace
1141 38 : eps_rho_rspace = dft_control%qs_control%eps_rho_rspace
1142 :
1143 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
1144 : maxco=maxco, &
1145 : maxlgto=maxlgto, &
1146 : maxsgf_set=maxsgf_set, &
1147 38 : basis_type=my_basis_type)
1148 :
1149 38 : distributed_grids = .FALSE.
1150 190 : DO igrid_level = 1, gridlevel_info%ngrid_levels
1151 38 : IF (rs_v(igrid_level)%desc%distributed) THEN
1152 152 : distributed_grids = .TRUE.
1153 : END IF
1154 : END DO
1155 :
1156 : nthread = 1
1157 38 : !$ nthread = omp_get_max_threads()
1158 :
1159 : ! get maximum numbers
1160 38 : maxset = 0
1161 38 : maxpgf = 0
1162 114 : DO ikind = 1, nkind
1163 : CALL get_qs_kind(qs_kind_set(ikind), &
1164 76 : basis_set=orb_basis_set, basis_type=my_basis_type)
1165 :
1166 76 : IF (.NOT. ASSOCIATED(orb_basis_set)) CYCLE
1167 :
1168 : CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
1169 76 : npgf=npgfa, nset=nseta)
1170 :
1171 76 : maxset = MAX(nseta, maxset)
1172 190 : maxpgf = MAX(MAXVAL(npgfa), maxpgf)
1173 : END DO
1174 :
1175 38 : ldsab = MAX(maxco, maxsgf_set, maxpgf*ncoset(maxlgto + 1))
1176 :
1177 : ! *** Allocate work storage ***
1178 38 : NULLIFY (habt, workt)
1179 38 : CALL reallocate(habt, 1, ldsab, 1, ldsab, 0, nthread)
1180 38 : CALL reallocate(workt, 1, ldsab, 1, maxsgf_set, 0, nthread)
1181 190 : ALLOCATE (rhab(ldsab, ldsab, 3))
1182 :
1183 152 : ALLOCATE (h_block(3))
1184 :
1185 38 : ithread = 0
1186 38 : !$ ithread = omp_get_thread_num()
1187 38 : work => workt(:, :, ithread)
1188 38 : hab => habt(:, :, ithread)
1189 62358 : hab(:, :) = 0._dp
1190 :
1191 38 : iset_old = -1; jset_old = -1
1192 38 : ikind_old = -1; jkind_old = -1
1193 :
1194 : ! Here we loop over gridlevels first, finalising the matrix after each grid level is
1195 : ! completed. On each grid level, we loop over atom pairs, which will only access
1196 : ! a single block of each matrix, so with OpenMP, each matrix block is only touched
1197 : ! by a single thread for each grid level
1198 190 : loop_gridlevels: DO igrid_level = 1, gridlevel_info%ngrid_levels
1199 608 : DO idir = 1, 3
1200 456 : CALL dbcsr_work_create(hmat(idir)%matrix, work_mutable=.TRUE., n=nthread)
1201 456 : CALL dbcsr_get_info(hmat(idir)%matrix, distribution=dist)
1202 456 : CALL dbcsr_distribution_get(dist, has_threads=has_threads)
1203 456 : !$ IF (.NOT. has_threads) &
1204 608 : !$ CPABORT("No thread distribution defined.")
1205 : END DO
1206 :
1207 494 : loop_pairs: DO ipair = 1, task_list%npairs(igrid_level)
1208 2299 : loop_tasks: DO itask = task_list%taskstart(ipair, igrid_level), task_list%taskstop(ipair, igrid_level)
1209 1805 : ilevel = tasks(itask)%grid_level
1210 1805 : img = tasks(itask)%image
1211 1805 : iatom = tasks(itask)%iatom
1212 1805 : jatom = tasks(itask)%jatom
1213 1805 : iset = tasks(itask)%iset
1214 1805 : jset = tasks(itask)%jset
1215 1805 : ipgf = tasks(itask)%ipgf
1216 1805 : jpgf = tasks(itask)%jpgf
1217 1805 : CPASSERT(img == 1)
1218 :
1219 : ! At the start of a block of tasks, get atom data (and kind data, if needed)
1220 1805 : IF (itask == task_list%taskstart(ipair, igrid_level)) THEN
1221 :
1222 342 : ikind = particle_set(iatom)%atomic_kind%kind_number
1223 342 : jkind = particle_set(jatom)%atomic_kind%kind_number
1224 :
1225 342 : IF (iatom <= jatom) THEN
1226 228 : brow = iatom
1227 228 : bcol = jatom
1228 : ELSE
1229 114 : brow = jatom
1230 114 : bcol = iatom
1231 : END IF
1232 :
1233 342 : IF (ikind /= ikind_old) THEN
1234 : CALL get_qs_kind(qs_kind_set(ikind), &
1235 38 : basis_set=orb_basis_set, basis_type=my_basis_type)
1236 :
1237 : CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
1238 : first_sgf=first_sgfa, &
1239 : lmax=la_max, &
1240 : lmin=la_min, &
1241 : npgf=npgfa, &
1242 : nset=nseta, &
1243 : nsgf_set=nsgfa, &
1244 : pgf_radius=rpgfa, &
1245 : set_radius=set_radius_a, &
1246 : sphi=sphi_a, &
1247 38 : zet=zeta)
1248 : END IF
1249 :
1250 342 : IF (jkind /= jkind_old) THEN
1251 : CALL get_qs_kind(qs_kind_set(jkind), &
1252 228 : basis_set=orb_basis_set, basis_type=my_basis_type)
1253 : CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
1254 : first_sgf=first_sgfb, &
1255 : lmax=lb_max, &
1256 : lmin=lb_min, &
1257 : npgf=npgfb, &
1258 : nset=nsetb, &
1259 : nsgf_set=nsgfb, &
1260 : pgf_radius=rpgfb, &
1261 : set_radius=set_radius_b, &
1262 : sphi=sphi_b, &
1263 228 : zet=zetb)
1264 :
1265 : END IF
1266 :
1267 1368 : DO idir = 1, 3
1268 1026 : NULLIFY (h_block(idir)%block)
1269 1026 : CALL dbcsr_get_block_p(hmat(idir)%matrix, brow, bcol, h_block(idir)%block, found)
1270 1368 : CPASSERT(found)
1271 : END DO
1272 :
1273 : ikind_old = ikind
1274 : jkind_old = jkind
1275 :
1276 : atom_pair_changed = .TRUE.
1277 :
1278 : ELSE
1279 :
1280 : atom_pair_changed = .FALSE.
1281 :
1282 : END IF
1283 :
1284 1805 : IF (atom_pair_changed .OR. iset_old /= iset .OR. jset_old /= jset) THEN
1285 : ! We reuse the hab(:, :) array to put the new integrals in.
1286 :
1287 342 : ncoa = npgfa(iset)*ncoset(la_max(iset))
1288 342 : ncoa_full = npgfa(iset)*ncoset(la_max(iset) + 1)
1289 342 : sgfa = first_sgfa(1, iset)
1290 342 : ncob = npgfb(jset)*ncoset(lb_max(jset))
1291 342 : ncob_full = npgfb(jset)*ncoset(lb_max(jset) + 1)
1292 342 : sgfb = first_sgfb(1, jset)
1293 :
1294 342 : IF (iatom <= jatom) THEN
1295 162108 : hab(1:ncoa_full, 1:ncob_full) = 0._dp
1296 : ELSE
1297 53010 : hab(1:ncob_full, 1:ncoa_full) = 0._dp
1298 : END IF
1299 :
1300 : iset_old = iset
1301 : jset_old = jset
1302 :
1303 : END IF
1304 :
1305 7220 : rab = tasks(itask)%rab
1306 7220 : dab = norm2(rab)
1307 : ! With and without MIC, rab(:) is the vector giving us the coordinates of rb.
1308 1805 : ra = pbc(particle_set(iatom)%r(:), cell)
1309 7220 : rb(:) = ra(:) + rab(:)
1310 1805 : rac = pbc(rc, ra, cell)
1311 7220 : rbc = rac + rab
1312 :
1313 1805 : zetp = zeta(ipgf, iset) + zetb(jpgf, jset)
1314 1805 : f = zetb(jpgf, jset)/zetp
1315 7220 : rp(:) = ra(:) + f*rab(:)
1316 :
1317 7220 : prefactor = EXP(-zeta(ipgf, iset)*f*DOT_PRODUCT(rab, rab))
1318 : radius = exp_radius_very_extended(la_min=la_min(iset), la_max=la_max(iset), &
1319 : lb_min=lb_min(jset), lb_max=lb_max(jset), &
1320 : ra=ra, rb=rb, rp=rp, &
1321 : zetp=zetp, eps=eps_rho_rspace, &
1322 1805 : prefactor=prefactor, cutoff=1.0_dp)
1323 :
1324 1805 : na1 = (ipgf - 1)*ncoset(la_max(iset) + 1) + 1
1325 1805 : na2 = ipgf*ncoset(la_max(iset) + 1)
1326 1805 : nb1 = (jpgf - 1)*ncoset(lb_max(jset) + 1) + 1
1327 1805 : nb2 = jpgf*ncoset(lb_max(jset) + 1)
1328 :
1329 1805 : IF (iatom <= jatom) THEN
1330 : CALL integrate_pgf_product( &
1331 : la_max(iset) + 1, zeta(ipgf, iset), la_min(iset), &
1332 : lb_max(jset) + 1, zetb(jpgf, jset), lb_min(jset), &
1333 : ra, rab, rs_v(igrid_level), &
1334 : hab, o1=na1 - 1, o2=nb1 - 1, &
1335 : radius=radius, &
1336 1216 : calculate_forces=.FALSE.)
1337 : ELSE
1338 2356 : rab_inv = -rab
1339 : CALL integrate_pgf_product( &
1340 : lb_max(jset) + 1, zetb(jpgf, jset), lb_min(jset), &
1341 : la_max(iset) + 1, zeta(ipgf, iset), la_min(iset), &
1342 : rb, rab_inv, rs_v(igrid_level), &
1343 : hab, o1=nb1 - 1, o2=na1 - 1, &
1344 : radius=radius, &
1345 589 : calculate_forces=.FALSE.)
1346 : END IF
1347 :
1348 1805 : new_set_pair_coming = .FALSE.
1349 1805 : atom_pair_done = .FALSE.
1350 1805 : IF (itask < task_list%taskstop(ipair, igrid_level)) THEN
1351 1463 : ilevel = tasks(itask + 1)%grid_level
1352 1463 : img = tasks(itask + 1)%image
1353 1463 : iatom = tasks(itask + 1)%iatom
1354 1463 : jatom = tasks(itask + 1)%jatom
1355 1463 : iset_new = tasks(itask + 1)%iset
1356 1463 : jset_new = tasks(itask + 1)%jset
1357 1463 : ipgf_new = tasks(itask + 1)%ipgf
1358 1463 : jpgf_new = tasks(itask + 1)%jpgf
1359 1463 : IF (iset_new /= iset .OR. jset_new /= jset) THEN
1360 : new_set_pair_coming = .TRUE.
1361 : END IF
1362 : ELSE
1363 : ! do not forget the last block
1364 : new_set_pair_coming = .TRUE.
1365 1805 : atom_pair_done = .TRUE.
1366 : END IF
1367 :
1368 342 : IF (new_set_pair_coming) THEN
1369 : ! Increase lx, ly, lz by one to account for the | r * b >
1370 342 : IF (iatom <= jatom) THEN
1371 : ! direction_Or = .false. so that we use rac
1372 : CALL ab_opr(la_max(iset), npgfa(iset), rpgfa(:, iset), 0, &
1373 : lb_max(jset), npgfb(jset), rpgfb(:, jset), 0, &
1374 228 : dab, hab(:, :), rhab(:, :, :), rac, rbc, direction_Or=.FALSE.)
1375 :
1376 : ELSE
1377 : ! direction_Or = .true. so that we use rac
1378 : CALL ab_opr(lb_max(jset), npgfb(jset), rpgfb(:, jset), 0, &
1379 : la_max(iset), npgfa(iset), rpgfa(:, iset), 0, &
1380 114 : dab, hab(:, :), rhab(:, :, :), rbc, rac, direction_Or=.TRUE.)
1381 : END IF
1382 :
1383 : ! contract the block into h if we're done with the current set pair
1384 1368 : DO idir = 1, 3
1385 1368 : IF (iatom <= jatom) THEN
1386 112860 : work = 0._dp
1387 301815 : work(1:ncoa, 1:nsgfb(jset)) = MATMUL(rhab(1:ncoa, 1:ncob, idir), sphi_b(1:ncob, sgfb:sgfb + nsgfb(jset) - 1))
1388 : h_block(idir)%block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) = &
1389 : h_block(idir)%block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) + &
1390 69255 : MATMUL(TRANSPOSE(sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1)), work(1:ncoa, 1:nsgfb(jset)))
1391 : ELSE
1392 36252 : work(1:ncob, 1:nsgfa(iset)) = MATMUL(rhab(1:ncob, 1:ncoa, idir), sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1))
1393 : h_block(idir)%block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) = &
1394 : h_block(idir)%block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) + &
1395 15903 : MATMUL(TRANSPOSE(sphi_b(1:ncob, sgfb:sgfb + nsgfb(jset) - 1)), work(1:ncob, 1:nsgfa(iset)))
1396 : END IF
1397 : END DO
1398 : END IF
1399 :
1400 : END DO loop_tasks
1401 : END DO loop_pairs
1402 :
1403 646 : DO idir = 1, 3
1404 608 : CALL dbcsr_finalize(hmat(idir)%matrix)
1405 : END DO
1406 :
1407 : END DO loop_gridlevels
1408 :
1409 : ! *** Release work storage ***
1410 38 : DEALLOCATE (habt, rhab, workt, h_block)
1411 :
1412 38 : CALL timestop(handle)
1413 :
1414 76 : END SUBROUTINE integrate_rv_rspace
1415 :
1416 : ! **************************************************************************************************
1417 : !> \brief Builds the overlap derivative wrt nuclear velocities
1418 : !> dS/dV = < mu | r | nu > * (nu - mu)
1419 : !> \param qs_env ...
1420 : !> \param matrix_dsdv ...
1421 : !> \param deltaR ...
1422 : !> \param rcc ...
1423 : !> \author Edward Ditler
1424 : ! **************************************************************************************************
1425 6 : SUBROUTINE build_dSdV_matrix(qs_env, matrix_dsdv, deltaR, rcc)
1426 : TYPE(qs_environment_type), POINTER :: qs_env
1427 : TYPE(dbcsr_p_type), DIMENSION(:) :: matrix_dsdv
1428 : REAL(KIND=dp), DIMENSION(:, :) :: deltaR
1429 : REAL(KIND=dp), DIMENSION(3) :: rcc
1430 :
1431 : CHARACTER(len=*), PARAMETER :: routineN = 'build_dSdV_matrix'
1432 :
1433 : INTEGER :: handle, i
1434 6 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, my_matrix_dsdv, &
1435 6 : my_matrix_dsdv2, my_matrix_mom
1436 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1437 6 : POINTER :: sab_all
1438 6 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1439 :
1440 6 : CALL timeset(routineN, handle)
1441 :
1442 6 : NULLIFY (my_matrix_mom, my_matrix_dsdv, my_matrix_dsdv2, sab_all, qs_kind_set)
1443 :
1444 : CALL get_qs_env(qs_env=qs_env, &
1445 : sab_all=sab_all, &
1446 : qs_kind_set=qs_kind_set, &
1447 6 : matrix_ks=matrix_ks)
1448 :
1449 : ! my_matrix_mom is needed because build_local_moment only works correctly with symmetric matrices
1450 6 : CALL dbcsr_allocate_matrix_set(my_matrix_dsdv, 3)
1451 6 : CALL dbcsr_allocate_matrix_set(my_matrix_dsdv2, 3)
1452 6 : CALL dbcsr_allocate_matrix_set(my_matrix_mom, 3)
1453 :
1454 24 : DO i = 1, 3
1455 18 : ALLOCATE (my_matrix_dsdv(i)%matrix)
1456 18 : ALLOCATE (my_matrix_dsdv2(i)%matrix)
1457 18 : ALLOCATE (my_matrix_mom(i)%matrix)
1458 :
1459 18 : CALL dbcsr_copy(my_matrix_dsdv(i)%matrix, matrix_dsdv(i)%matrix)
1460 18 : CALL dbcsr_copy(my_matrix_dsdv2(i)%matrix, matrix_dsdv(i)%matrix)
1461 18 : CALL dbcsr_copy(my_matrix_mom(i)%matrix, matrix_ks(1)%matrix)
1462 :
1463 18 : CALL dbcsr_set(my_matrix_dsdv2(i)%matrix, 0.0_dp)
1464 18 : CALL dbcsr_set(my_matrix_dsdv(i)%matrix, 0.0_dp)
1465 18 : CALL dbcsr_set(my_matrix_mom(i)%matrix, 0.0_dp)
1466 24 : CALL dbcsr_set(matrix_dsdv(i)%matrix, 0.0_dp)
1467 : END DO
1468 :
1469 : CALL build_local_moment_matrix(qs_env, my_matrix_mom, 1, ref_point=rcc, &
1470 6 : neighbor_image=.TRUE.)
1471 :
1472 24 : DO i = 1, 3
1473 18 : CALL dbcsr_desymmetrize(my_matrix_mom(i)%matrix, my_matrix_dsdv(i)%matrix)
1474 24 : CALL dbcsr_copy(my_matrix_dsdv2(i)%matrix, my_matrix_dsdv(i)%matrix)
1475 : END DO
1476 :
1477 : ! delta_nu^A <mu|r|nu>
1478 : CALL hr_mult_by_delta_3d(my_matrix_dsdv, qs_kind_set, "ORB", sab_all, &
1479 6 : deltaR, direction_Or=.TRUE.)
1480 : ! -delta_mu^A <mu|r|nu>
1481 : CALL hr_mult_by_delta_3d(my_matrix_dsdv2, qs_kind_set, "ORB", sab_all, &
1482 6 : deltaR, direction_Or=.FALSE.)
1483 24 : DO i = 1, 3
1484 18 : CALL dbcsr_copy(matrix_dsdv(i)%matrix, my_matrix_dsdv(i)%matrix)
1485 24 : CALL dbcsr_add(matrix_dsdv(i)%matrix, my_matrix_dsdv2(i)%matrix, 1.0_dp, -1.0_dp)
1486 : END DO
1487 :
1488 6 : CALL dbcsr_deallocate_matrix_set(my_matrix_dsdv)
1489 6 : CALL dbcsr_deallocate_matrix_set(my_matrix_dsdv2)
1490 6 : CALL dbcsr_deallocate_matrix_set(my_matrix_mom)
1491 :
1492 6 : CALL timestop(handle)
1493 :
1494 6 : END SUBROUTINE build_dSdV_matrix
1495 :
1496 : ! **************************************************************************************************
1497 : !> \brief Build the two ordered nonlocal second-position products.
1498 : !> \param matrix_rcomr ...
1499 : !> \param matrix_rrcom ...
1500 : !> \param qs_kind_set ...
1501 : !> \param sab_all ...
1502 : !> \param sap_ppnl ...
1503 : !> \param eps_ppnl ...
1504 : !> \param particle_set ...
1505 : !> \param cell ...
1506 : !> \author Edward Ditler, Tomas Zimmermann
1507 : ! **************************************************************************************************
1508 2 : SUBROUTINE build_com_rpnl_r(matrix_rcomr, matrix_rrcom, qs_kind_set, sab_all, sap_ppnl, eps_ppnl, &
1509 : particle_set, cell)
1510 :
1511 : TYPE(dbcsr_p_type), DIMENSION(:, :) :: matrix_rcomr, matrix_rrcom
1512 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1513 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1514 : POINTER :: sab_all, sap_ppnl
1515 : REAL(KIND=dp), INTENT(IN) :: eps_ppnl
1516 : TYPE(particle_type), DIMENSION(:), INTENT(IN), &
1517 : POINTER :: particle_set
1518 : TYPE(cell_type), POINTER :: cell
1519 :
1520 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_com_rpnl_r'
1521 :
1522 : INTEGER :: handle, i, iab, iac, iatom, ibc, icol, &
1523 : ikind, irow, j, jatom, jkind, kac, &
1524 : kbc, kkind, na, natom, nb, nkind, np, &
1525 : slot
1526 : INTEGER, DIMENSION(3) :: cell_b
1527 : LOGICAL :: found, ppnl_present
1528 : REAL(KIND=dp), DIMENSION(3) :: rab
1529 2 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: achint, acint, bchint, bcint
1530 : TYPE(alist_type), POINTER :: alist_ac, alist_bc
1531 54 : TYPE(block_p_type), DIMENSION(3, 3, 2) :: blocks_rvr
1532 2 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set
1533 : TYPE(gto_basis_set_type), POINTER :: orb_basis_set
1534 2 : TYPE(sap_int_type), DIMENSION(:), POINTER :: sap_int
1535 :
1536 : !$ INTEGER(kind=omp_lock_kind), &
1537 2 : !$ ALLOCATABLE, DIMENSION(:) :: locks
1538 : !$ INTEGER :: lock_num, hash
1539 : !$ INTEGER, PARAMETER :: nlock = 501
1540 :
1541 2 : ppnl_present = ASSOCIATED(sap_ppnl)
1542 2 : IF (.NOT. ppnl_present) RETURN
1543 :
1544 2 : CALL timeset(routineN, handle)
1545 2 : nkind = SIZE(qs_kind_set)
1546 2 : natom = SIZE(particle_set)
1547 :
1548 : ! sap_int needs to be shared as multiple threads need to access this
1549 2 : NULLIFY (sap_int)
1550 14 : ALLOCATE (sap_int(nkind*nkind))
1551 10 : DO i = 1, nkind*nkind
1552 8 : NULLIFY (sap_int(i)%alist, sap_int(i)%asort, sap_int(i)%aindex)
1553 10 : sap_int(i)%nalist = 0
1554 : END DO
1555 :
1556 : ! We put zero as a reference point, because actually in the integrals we need two different ones:
1557 : ! < a | (r - R^\lambda_\beta) * [V, r_\alpha - R^\eta_\alpha] | b >
1558 : ! The first reference point can be added in a seperate step as the term will be
1559 : ! - R^\lambda_\beta * < a | [V, r_\alpha] | b >
1560 : ! = + R^\lambda_\beta * < a | [r_\alpha, V] | b >
1561 : ! The second reference point is not important, because it disappears in the commutator
1562 : CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, nder=2, moment_mode=.TRUE., &
1563 2 : particle_set=particle_set, cell=cell, refpoint=[0._dp, 0._dp, 0._dp])
1564 :
1565 : ! *** Set up a sorting index
1566 2 : CALL sap_sort(sap_int)
1567 :
1568 10 : ALLOCATE (basis_set(nkind))
1569 6 : DO ikind = 1, nkind
1570 4 : CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
1571 6 : IF (ASSOCIATED(orb_basis_set)) THEN
1572 4 : basis_set(ikind)%gto_basis_set => orb_basis_set
1573 : ELSE
1574 0 : NULLIFY (basis_set(ikind)%gto_basis_set)
1575 : END IF
1576 : END DO
1577 :
1578 : ! *** All integrals needed have been calculated and stored in sap_int
1579 : ! *** We now calculate the ordered second-position product matrix elements
1580 :
1581 : !$OMP PARALLEL &
1582 : !$OMP DEFAULT (NONE) &
1583 : !$OMP SHARED (basis_set, matrix_rcomr, matrix_rrcom, &
1584 : !$OMP sap_int, nkind, eps_ppnl, locks, sab_all) &
1585 : !$OMP PRIVATE (ikind, jkind, iatom, jatom, cell_b, rab, &
1586 : !$OMP iab, irow, icol, blocks_rvr, lock_num, &
1587 : !$OMP found, iac, ibc, alist_ac, alist_bc, &
1588 : !$OMP na, np, nb, kkind, kac, kbc, i, j, &
1589 2 : !$OMP hash, natom, acint, bcint, achint, bchint)
1590 :
1591 : !$OMP SINGLE
1592 : !$ ALLOCATE (locks(nlock))
1593 : !$OMP END SINGLE
1594 :
1595 : !$OMP DO
1596 : !$ DO lock_num = 1, nlock
1597 : !$ call omp_init_lock(locks(lock_num))
1598 : !$ END DO
1599 : !$OMP END DO
1600 :
1601 : !$OMP DO SCHEDULE(GUIDED)
1602 :
1603 : DO slot = 1, sab_all(1)%nl_size
1604 :
1605 : ikind = sab_all(1)%nlist_task(slot)%ikind
1606 : jkind = sab_all(1)%nlist_task(slot)%jkind
1607 : iatom = sab_all(1)%nlist_task(slot)%iatom
1608 : jatom = sab_all(1)%nlist_task(slot)%jatom
1609 : cell_b(:) = sab_all(1)%nlist_task(slot)%cell(:)
1610 : rab(1:3) = sab_all(1)%nlist_task(slot)%r(1:3)
1611 :
1612 : IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
1613 : IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
1614 : iab = ikind + nkind*(jkind - 1)
1615 :
1616 : ! *** Create matrix blocks for a new matrix block column ***
1617 : irow = iatom
1618 : icol = jatom
1619 : DO i = 1, 3
1620 : DO j = 1, 3
1621 : ! t_alpha = MOD(i - 1, 3) + 1
1622 : ! t_beta = FLOOR(REAL(i - 1, dp)/3._dp) + 1
1623 :
1624 : CALL dbcsr_get_block_p(matrix_rcomr(i, j)%matrix, irow, icol, blocks_rvr(i, j, 1)%block, found)
1625 : CPASSERT(found)
1626 : CALL dbcsr_get_block_p(matrix_rrcom(i, j)%matrix, irow, icol, blocks_rvr(i, j, 2)%block, found)
1627 : CPASSERT(found)
1628 : END DO
1629 : END DO
1630 :
1631 : ! loop over all kinds for projector atom
1632 : DO kkind = 1, nkind
1633 : iac = ikind + nkind*(kkind - 1)
1634 : ibc = jkind + nkind*(kkind - 1)
1635 : IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
1636 : IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
1637 : CALL get_alist(sap_int(iac), alist_ac, iatom)
1638 : CALL get_alist(sap_int(ibc), alist_bc, jatom)
1639 : IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
1640 : IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
1641 : DO kac = 1, alist_ac%nclist
1642 : DO kbc = 1, alist_bc%nclist
1643 : IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
1644 :
1645 : ! Some documention, considering the C1 O1 O2 molecule
1646 : ! The integrals are <a|p>
1647 : ! sap_int(1:2, 1:2) -> [(a=C, p=C), (a=C, p=O), (a=O, p=C), (a=O, p=0)]
1648 : ! the (a=O, p=C) entry has an alist
1649 : ! alist has two elements: O1, O2
1650 : ! alist(O1) -> clist(C1)%acint are the integrals
1651 : ! alist(O2) -> clist(C1)%acint are the integrals
1652 :
1653 : IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
1654 : IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
1655 : acint => alist_ac%clist(kac)%acint
1656 : bcint => alist_bc%clist(kbc)%acint
1657 : achint => alist_ac%clist(kac)%achint
1658 : bchint => alist_bc%clist(kbc)%achint
1659 : na = SIZE(acint, 1)
1660 : np = SIZE(acint, 2)
1661 : nb = SIZE(bcint, 1)
1662 : !$ hash = MOD((iatom - 1)*natom + jatom, nlock) + 1
1663 : !$ CALL omp_set_lock(locks(hash))
1664 :
1665 : DO i = 1, 3
1666 : DO j = 1, 3
1667 : ! matrix_rcomr(i, j) = (Vnl*r_i)*r_j - (r_i*Vnl)*r_j
1668 : blocks_rvr(i, j, 1)%block(1:na, 1:nb) = blocks_rvr(i, j, 1)%block(1:na, 1:nb) + &
1669 : MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_rr(i, j)))) - &
1670 : MATMUL(achint(1:na, 1:np, bi_r(i)), TRANSPOSE(bcint(1:nb, 1:np, bi_r(j))))
1671 :
1672 : ! matrix_rrcom(i, j) = r_j*(Vnl*r_i) - r_j*(r_i*Vnl)
1673 : blocks_rvr(i, j, 2)%block(1:na, 1:nb) = blocks_rvr(i, j, 2)%block(1:na, 1:nb) + &
1674 : MATMUL(achint(1:na, 1:np, bi_r(j)), TRANSPOSE(bcint(1:nb, 1:np, bi_r(i)))) - &
1675 : MATMUL(achint(1:na, 1:np, bi_rr(i, j)), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
1676 : END DO
1677 : END DO
1678 :
1679 : !$ CALL omp_unset_lock(locks(hash))
1680 : EXIT ! We have found a match and there can be only one single match
1681 : END IF
1682 : END DO
1683 : END DO
1684 : END DO
1685 : DO i = 1, 3
1686 : DO j = 1, 3
1687 : NULLIFY (blocks_rvr(i, j, 1)%block)
1688 : NULLIFY (blocks_rvr(i, j, 2)%block)
1689 : END DO
1690 : END DO
1691 : END DO
1692 :
1693 : !$OMP DO
1694 : !$ DO lock_num = 1, nlock
1695 : !$ call omp_destroy_lock(locks(lock_num))
1696 : !$ END DO
1697 : !$OMP END DO
1698 :
1699 : !$OMP SINGLE
1700 : !$ DEALLOCATE (locks)
1701 : !$OMP END SINGLE NOWAIT
1702 :
1703 : !$OMP END PARALLEL
1704 :
1705 2 : CALL release_sap_int(sap_int)
1706 :
1707 2 : DEALLOCATE (basis_set)
1708 :
1709 2 : CALL timestop(handle)
1710 :
1711 6 : END SUBROUTINE build_com_rpnl_r
1712 :
1713 : ! **************************************************************************************************
1714 : !> \brief Calculate the double commutator [[Vnl, r], r]
1715 : !> \param matrix_rv ...
1716 : !> \param qs_kind_set ...
1717 : !> \param sab_orb ...
1718 : !> \param sap_ppnl ...
1719 : !> \param eps_ppnl ...
1720 : !> \param particle_set ...
1721 : !> \param pseudoatom Only consider pseudopotentials on atom lambda
1722 : !> \author Edward Ditler
1723 : ! **************************************************************************************************
1724 6 : SUBROUTINE build_dcom_rpnl(matrix_rv, qs_kind_set, sab_orb, sap_ppnl, eps_ppnl, particle_set, pseudoatom)
1725 :
1726 : TYPE(dbcsr_p_type), DIMENSION(:, :) :: matrix_rv
1727 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1728 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1729 : POINTER :: sab_orb, sap_ppnl
1730 : REAL(KIND=dp), INTENT(IN) :: eps_ppnl
1731 : TYPE(particle_type), DIMENSION(:), INTENT(IN), &
1732 : POINTER :: particle_set
1733 : INTEGER, INTENT(IN) :: pseudoatom
1734 :
1735 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_dcom_rpnl'
1736 :
1737 : INTEGER :: handle, i, iab, iac, iatom, ibc, icol, &
1738 : ikind, irow, j, jatom, jkind, kac, &
1739 : kbc, kkind, na, natom, nb, nkind, np, &
1740 : slot
1741 : INTEGER, DIMENSION(3) :: cell_b
1742 : LOGICAL :: found, ppnl_present
1743 : REAL(KIND=dp), DIMENSION(3) :: rab
1744 6 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: achint, acint, bchint, bcint
1745 : TYPE(alist_type), POINTER :: alist_ac, alist_bc
1746 78 : TYPE(block_p_type), DIMENSION(3, 3) :: blocks_rv
1747 6 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set
1748 : TYPE(gto_basis_set_type), POINTER :: orb_basis_set
1749 6 : TYPE(sap_int_type), DIMENSION(:), POINTER :: sap_int
1750 :
1751 : !$ INTEGER(kind=omp_lock_kind), &
1752 6 : !$ ALLOCATABLE, DIMENSION(:) :: locks
1753 : !$ INTEGER :: lock_num, hash
1754 : !$ INTEGER, PARAMETER :: nlock = 501
1755 :
1756 6 : ppnl_present = ASSOCIATED(sap_ppnl)
1757 6 : IF (.NOT. ppnl_present) RETURN
1758 :
1759 6 : CALL timeset(routineN, handle)
1760 6 : nkind = SIZE(qs_kind_set)
1761 6 : natom = SIZE(particle_set)
1762 :
1763 : ! sap_int needs to be shared as multiple threads need to access this
1764 6 : NULLIFY (sap_int)
1765 42 : ALLOCATE (sap_int(nkind*nkind))
1766 30 : DO i = 1, nkind*nkind
1767 24 : NULLIFY (sap_int(i)%alist, sap_int(i)%asort, sap_int(i)%aindex)
1768 30 : sap_int(i)%nalist = 0
1769 : END DO
1770 :
1771 : ! "nder" in moment_mode is "order"
1772 : CALL build_sap_ints(sap_int, sap_ppnl, qs_kind_set, nder=2, moment_mode=.TRUE., &
1773 6 : particle_set=particle_set, pseudoatom=pseudoatom)
1774 :
1775 : ! *** Set up a sorting index
1776 6 : CALL sap_sort(sap_int)
1777 :
1778 30 : ALLOCATE (basis_set(nkind))
1779 18 : DO ikind = 1, nkind
1780 12 : CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
1781 18 : IF (ASSOCIATED(orb_basis_set)) THEN
1782 12 : basis_set(ikind)%gto_basis_set => orb_basis_set
1783 : ELSE
1784 0 : NULLIFY (basis_set(ikind)%gto_basis_set)
1785 : END IF
1786 : END DO
1787 :
1788 : ! *** All integrals needed have been calculated and stored in sap_int
1789 : ! *** We now calculate the commutator matrix elements
1790 :
1791 : !$OMP PARALLEL &
1792 : !$OMP DEFAULT (NONE) &
1793 : !$OMP SHARED (basis_set, matrix_rv, &
1794 : !$OMP sap_int, nkind, eps_ppnl, locks, sab_orb) &
1795 : !$OMP PRIVATE (ikind, jkind, iatom, jatom, cell_b, rab, &
1796 : !$OMP iab, irow, icol, blocks_rv, lock_num, &
1797 : !$OMP found, iac, ibc, alist_ac, alist_bc, &
1798 : !$OMP na, np, nb, kkind, kac, kbc, i, j, &
1799 6 : !$OMP hash, natom, acint, bcint, achint, bchint)
1800 :
1801 : !$OMP SINGLE
1802 : !$ ALLOCATE (locks(nlock))
1803 : !$OMP END SINGLE
1804 :
1805 : !$OMP DO
1806 : !$ DO lock_num = 1, nlock
1807 : !$ call omp_init_lock(locks(lock_num))
1808 : !$ END DO
1809 : !$OMP END DO
1810 :
1811 : !$OMP DO SCHEDULE(GUIDED)
1812 :
1813 : DO slot = 1, sab_orb(1)%nl_size
1814 :
1815 : ikind = sab_orb(1)%nlist_task(slot)%ikind
1816 : jkind = sab_orb(1)%nlist_task(slot)%jkind
1817 : iatom = sab_orb(1)%nlist_task(slot)%iatom
1818 : jatom = sab_orb(1)%nlist_task(slot)%jatom
1819 : cell_b(:) = sab_orb(1)%nlist_task(slot)%cell(:)
1820 : rab(1:3) = sab_orb(1)%nlist_task(slot)%r(1:3)
1821 :
1822 : IF (.NOT. ASSOCIATED(basis_set(ikind)%gto_basis_set)) CYCLE
1823 : IF (.NOT. ASSOCIATED(basis_set(jkind)%gto_basis_set)) CYCLE
1824 : iab = ikind + nkind*(jkind - 1)
1825 :
1826 : ! *** Create matrix blocks for a new matrix block column ***
1827 : IF (iatom <= jatom) THEN
1828 : irow = iatom
1829 : icol = jatom
1830 : ELSE
1831 : irow = jatom
1832 : icol = iatom
1833 : END IF
1834 :
1835 : DO i = 1, 3
1836 : DO j = 1, 3
1837 : CALL dbcsr_get_block_p(matrix_rv(i, j)%matrix, irow, icol, blocks_rv(i, j)%block, found)
1838 : blocks_rv(i, j)%block = 0._dp
1839 : CPASSERT(found)
1840 : END DO
1841 : END DO
1842 :
1843 : ! loop over all kinds for projector atom
1844 : DO kkind = 1, nkind
1845 : iac = ikind + nkind*(kkind - 1)
1846 : ibc = jkind + nkind*(kkind - 1)
1847 : IF (.NOT. ASSOCIATED(sap_int(iac)%alist)) CYCLE
1848 : IF (.NOT. ASSOCIATED(sap_int(ibc)%alist)) CYCLE
1849 : CALL get_alist(sap_int(iac), alist_ac, iatom)
1850 : CALL get_alist(sap_int(ibc), alist_bc, jatom)
1851 : IF (.NOT. ASSOCIATED(alist_ac)) CYCLE
1852 : IF (.NOT. ASSOCIATED(alist_bc)) CYCLE
1853 : DO kac = 1, alist_ac%nclist
1854 : DO kbc = 1, alist_bc%nclist
1855 : IF (alist_ac%clist(kac)%catom /= alist_bc%clist(kbc)%catom) CYCLE
1856 : IF (ALL(cell_b + alist_bc%clist(kbc)%cell - alist_ac%clist(kac)%cell == 0)) THEN
1857 : IF (alist_ac%clist(kac)%maxac*alist_bc%clist(kbc)%maxach < eps_ppnl) CYCLE
1858 : acint => alist_ac%clist(kac)%acint
1859 : bcint => alist_bc%clist(kbc)%acint
1860 : achint => alist_ac%clist(kac)%achint
1861 : bchint => alist_bc%clist(kbc)%achint
1862 : na = SIZE(acint, 1)
1863 : np = SIZE(acint, 2)
1864 : nb = SIZE(bcint, 1)
1865 : !$ hash = MOD((iatom - 1)*natom + jatom, nlock) + 1
1866 : !$ CALL omp_set_lock(locks(hash))
1867 : ! Template:
1868 : ! blocks_rv(1)%block(1:na, 1:nb) = blocks_rv(1)%block(1:na, 1:nb) + &
1869 : ! MATMUL(achint(1:na, 1:np, 2), TRANSPOSE(bcint(1:nb, 1:np, 1))) ! xV
1870 : IF (iatom <= jatom) THEN
1871 : ! r_alpha*Vnl*r_beta
1872 : blocks_rv(1, 1)%block(1:na, 1:nb) = blocks_rv(1, 1)%block(1:na, 1:nb) + &
1873 : MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
1874 :
1875 : blocks_rv(1, 2)%block(1:na, 1:nb) = blocks_rv(1, 2)%block(1:na, 1:nb) + &
1876 : MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
1877 :
1878 : blocks_rv(1, 3)%block(1:na, 1:nb) = blocks_rv(1, 3)%block(1:na, 1:nb) + &
1879 : MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
1880 :
1881 : blocks_rv(2, 1)%block(1:na, 1:nb) = blocks_rv(2, 1)%block(1:na, 1:nb) + &
1882 : MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
1883 :
1884 : blocks_rv(2, 2)%block(1:na, 1:nb) = blocks_rv(2, 2)%block(1:na, 1:nb) + &
1885 : MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
1886 :
1887 : blocks_rv(2, 3)%block(1:na, 1:nb) = blocks_rv(2, 3)%block(1:na, 1:nb) + &
1888 : MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
1889 :
1890 : blocks_rv(3, 1)%block(1:na, 1:nb) = blocks_rv(3, 1)%block(1:na, 1:nb) + &
1891 : MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
1892 :
1893 : blocks_rv(3, 2)%block(1:na, 1:nb) = blocks_rv(3, 2)%block(1:na, 1:nb) + &
1894 : MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
1895 :
1896 : blocks_rv(3, 3)%block(1:na, 1:nb) = blocks_rv(3, 3)%block(1:na, 1:nb) + &
1897 : MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
1898 :
1899 : ! -r_alpha*r_beta*Vnl
1900 : blocks_rv(1, 1)%block(1:na, 1:nb) = blocks_rv(1, 1)%block(1:na, 1:nb) - &
1901 : MATMUL(achint(1:na, 1:np, bi_xx), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
1902 :
1903 : blocks_rv(1, 2)%block(1:na, 1:nb) = blocks_rv(1, 2)%block(1:na, 1:nb) - &
1904 : MATMUL(achint(1:na, 1:np, bi_xy), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
1905 :
1906 : blocks_rv(1, 3)%block(1:na, 1:nb) = blocks_rv(1, 3)%block(1:na, 1:nb) - &
1907 : MATMUL(achint(1:na, 1:np, bi_xz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
1908 :
1909 : blocks_rv(2, 1)%block(1:na, 1:nb) = blocks_rv(2, 1)%block(1:na, 1:nb) - &
1910 : MATMUL(achint(1:na, 1:np, bi_xy), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
1911 :
1912 : blocks_rv(2, 2)%block(1:na, 1:nb) = blocks_rv(2, 2)%block(1:na, 1:nb) - &
1913 : MATMUL(achint(1:na, 1:np, bi_yy), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
1914 :
1915 : blocks_rv(2, 3)%block(1:na, 1:nb) = blocks_rv(2, 3)%block(1:na, 1:nb) - &
1916 : MATMUL(achint(1:na, 1:np, bi_yz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
1917 :
1918 : blocks_rv(3, 1)%block(1:na, 1:nb) = blocks_rv(3, 1)%block(1:na, 1:nb) - &
1919 : MATMUL(achint(1:na, 1:np, bi_xz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
1920 :
1921 : blocks_rv(3, 2)%block(1:na, 1:nb) = blocks_rv(3, 2)%block(1:na, 1:nb) - &
1922 : MATMUL(achint(1:na, 1:np, bi_yz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
1923 :
1924 : blocks_rv(3, 3)%block(1:na, 1:nb) = blocks_rv(3, 3)%block(1:na, 1:nb) - &
1925 : MATMUL(achint(1:na, 1:np, bi_zz), TRANSPOSE(bcint(1:nb, 1:np, bi_1)))
1926 :
1927 : ! -Vnl*r_beta*r_alpha
1928 : blocks_rv(1, 1)%block(1:na, 1:nb) = blocks_rv(1, 1)%block(1:na, 1:nb) - &
1929 : MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xx)))
1930 :
1931 : blocks_rv(1, 2)%block(1:na, 1:nb) = blocks_rv(1, 2)%block(1:na, 1:nb) - &
1932 : MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xy)))
1933 :
1934 : blocks_rv(1, 3)%block(1:na, 1:nb) = blocks_rv(1, 3)%block(1:na, 1:nb) - &
1935 : MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xz)))
1936 :
1937 : blocks_rv(2, 1)%block(1:na, 1:nb) = blocks_rv(2, 1)%block(1:na, 1:nb) - &
1938 : MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xy)))
1939 :
1940 : blocks_rv(2, 2)%block(1:na, 1:nb) = blocks_rv(2, 2)%block(1:na, 1:nb) - &
1941 : MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_yy)))
1942 :
1943 : blocks_rv(2, 3)%block(1:na, 1:nb) = blocks_rv(2, 3)%block(1:na, 1:nb) - &
1944 : MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_yz)))
1945 :
1946 : blocks_rv(3, 1)%block(1:na, 1:nb) = blocks_rv(3, 1)%block(1:na, 1:nb) - &
1947 : MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_xz)))
1948 :
1949 : blocks_rv(3, 2)%block(1:na, 1:nb) = blocks_rv(3, 2)%block(1:na, 1:nb) - &
1950 : MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_yz)))
1951 :
1952 : blocks_rv(3, 3)%block(1:na, 1:nb) = blocks_rv(3, 3)%block(1:na, 1:nb) - &
1953 : MATMUL(achint(1:na, 1:np, bi_1), TRANSPOSE(bcint(1:nb, 1:np, bi_zz)))
1954 :
1955 : ! +r_beta*Vnl*r_alpha
1956 : blocks_rv(1, 1)%block(1:na, 1:nb) = blocks_rv(1, 1)%block(1:na, 1:nb) + &
1957 : MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
1958 :
1959 : blocks_rv(1, 2)%block(1:na, 1:nb) = blocks_rv(1, 2)%block(1:na, 1:nb) + &
1960 : MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
1961 :
1962 : blocks_rv(1, 3)%block(1:na, 1:nb) = blocks_rv(1, 3)%block(1:na, 1:nb) + &
1963 : MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_x)))
1964 :
1965 : blocks_rv(2, 1)%block(1:na, 1:nb) = blocks_rv(2, 1)%block(1:na, 1:nb) + &
1966 : MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
1967 :
1968 : blocks_rv(2, 2)%block(1:na, 1:nb) = blocks_rv(2, 2)%block(1:na, 1:nb) + &
1969 : MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
1970 :
1971 : blocks_rv(2, 3)%block(1:na, 1:nb) = blocks_rv(2, 3)%block(1:na, 1:nb) + &
1972 : MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_y)))
1973 :
1974 : blocks_rv(3, 1)%block(1:na, 1:nb) = blocks_rv(3, 1)%block(1:na, 1:nb) + &
1975 : MATMUL(achint(1:na, 1:np, bi_x), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
1976 :
1977 : blocks_rv(3, 2)%block(1:na, 1:nb) = blocks_rv(3, 2)%block(1:na, 1:nb) + &
1978 : MATMUL(achint(1:na, 1:np, bi_y), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
1979 :
1980 : blocks_rv(3, 3)%block(1:na, 1:nb) = blocks_rv(3, 3)%block(1:na, 1:nb) + &
1981 : MATMUL(achint(1:na, 1:np, bi_z), TRANSPOSE(bcint(1:nb, 1:np, bi_z)))
1982 : ELSE
1983 : ! r_alpha*Vnl*r_beta
1984 : blocks_rv(1, 1)%block(1:nb, 1:na) = blocks_rv(1, 1)%block(1:nb, 1:na) + &
1985 : MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_x)))
1986 :
1987 : blocks_rv(1, 2)%block(1:nb, 1:na) = blocks_rv(1, 2)%block(1:nb, 1:na) + &
1988 : MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_y)))
1989 :
1990 : blocks_rv(1, 3)%block(1:nb, 1:na) = blocks_rv(1, 3)%block(1:nb, 1:na) + &
1991 : MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_z)))
1992 :
1993 : blocks_rv(2, 1)%block(1:nb, 1:na) = blocks_rv(2, 1)%block(1:nb, 1:na) + &
1994 : MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_x)))
1995 :
1996 : blocks_rv(2, 2)%block(1:nb, 1:na) = blocks_rv(2, 2)%block(1:nb, 1:na) + &
1997 : MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_y)))
1998 :
1999 : blocks_rv(2, 3)%block(1:nb, 1:na) = blocks_rv(2, 3)%block(1:nb, 1:na) + &
2000 : MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_z)))
2001 :
2002 : blocks_rv(3, 1)%block(1:nb, 1:na) = blocks_rv(3, 1)%block(1:nb, 1:na) + &
2003 : MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_x)))
2004 :
2005 : blocks_rv(3, 2)%block(1:nb, 1:na) = blocks_rv(3, 2)%block(1:nb, 1:na) + &
2006 : MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_y)))
2007 :
2008 : blocks_rv(3, 3)%block(1:nb, 1:na) = blocks_rv(3, 3)%block(1:nb, 1:na) + &
2009 : MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_z)))
2010 :
2011 : ! -r_alpha*r_beta*Vnl
2012 : blocks_rv(1, 1)%block(1:nb, 1:na) = blocks_rv(1, 1)%block(1:nb, 1:na) - &
2013 : MATMUL(bchint(1:nb, 1:np, bi_xx), TRANSPOSE(acint(1:na, 1:np, bi_1)))
2014 :
2015 : blocks_rv(1, 2)%block(1:nb, 1:na) = blocks_rv(1, 2)%block(1:nb, 1:na) - &
2016 : MATMUL(bchint(1:nb, 1:np, bi_xy), TRANSPOSE(acint(1:na, 1:np, bi_1)))
2017 :
2018 : blocks_rv(1, 3)%block(1:nb, 1:na) = blocks_rv(1, 3)%block(1:nb, 1:na) - &
2019 : MATMUL(bchint(1:nb, 1:np, bi_xz), TRANSPOSE(acint(1:na, 1:np, bi_1)))
2020 :
2021 : blocks_rv(2, 1)%block(1:nb, 1:na) = blocks_rv(2, 1)%block(1:nb, 1:na) - &
2022 : MATMUL(bchint(1:nb, 1:np, bi_xy), TRANSPOSE(acint(1:na, 1:np, bi_1)))
2023 :
2024 : blocks_rv(2, 2)%block(1:nb, 1:na) = blocks_rv(2, 2)%block(1:nb, 1:na) - &
2025 : MATMUL(bchint(1:nb, 1:np, bi_yy), TRANSPOSE(acint(1:na, 1:np, bi_1)))
2026 :
2027 : blocks_rv(2, 3)%block(1:nb, 1:na) = blocks_rv(2, 3)%block(1:nb, 1:na) - &
2028 : MATMUL(bchint(1:nb, 1:np, bi_yz), TRANSPOSE(acint(1:na, 1:np, bi_1)))
2029 :
2030 : blocks_rv(3, 1)%block(1:nb, 1:na) = blocks_rv(3, 1)%block(1:nb, 1:na) - &
2031 : MATMUL(bchint(1:nb, 1:np, bi_xz), TRANSPOSE(acint(1:na, 1:np, bi_1)))
2032 :
2033 : blocks_rv(3, 2)%block(1:nb, 1:na) = blocks_rv(3, 2)%block(1:nb, 1:na) - &
2034 : MATMUL(bchint(1:nb, 1:np, bi_yz), TRANSPOSE(acint(1:na, 1:np, bi_1)))
2035 :
2036 : blocks_rv(3, 3)%block(1:nb, 1:na) = blocks_rv(3, 3)%block(1:nb, 1:na) - &
2037 : MATMUL(bchint(1:nb, 1:np, bi_zz), TRANSPOSE(acint(1:na, 1:np, bi_1)))
2038 :
2039 : ! -Vnl*r_beta*r_alpha
2040 : blocks_rv(1, 1)%block(1:nb, 1:na) = blocks_rv(1, 1)%block(1:nb, 1:na) - &
2041 : MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_xx)))
2042 :
2043 : blocks_rv(1, 2)%block(1:nb, 1:na) = blocks_rv(1, 2)%block(1:nb, 1:na) - &
2044 : MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_xy)))
2045 :
2046 : blocks_rv(1, 3)%block(1:nb, 1:na) = blocks_rv(1, 3)%block(1:nb, 1:na) - &
2047 : MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_xz)))
2048 :
2049 : blocks_rv(2, 1)%block(1:nb, 1:na) = blocks_rv(2, 1)%block(1:nb, 1:na) - &
2050 : MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_xy)))
2051 :
2052 : blocks_rv(2, 2)%block(1:nb, 1:na) = blocks_rv(2, 2)%block(1:nb, 1:na) - &
2053 : MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_yy)))
2054 :
2055 : blocks_rv(2, 3)%block(1:nb, 1:na) = blocks_rv(2, 3)%block(1:nb, 1:na) - &
2056 : MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_yz)))
2057 :
2058 : blocks_rv(3, 1)%block(1:nb, 1:na) = blocks_rv(3, 1)%block(1:nb, 1:na) - &
2059 : MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_xz)))
2060 :
2061 : blocks_rv(3, 2)%block(1:nb, 1:na) = blocks_rv(3, 2)%block(1:nb, 1:na) - &
2062 : MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_yz)))
2063 :
2064 : blocks_rv(3, 3)%block(1:nb, 1:na) = blocks_rv(3, 3)%block(1:nb, 1:na) - &
2065 : MATMUL(bchint(1:nb, 1:np, bi_1), TRANSPOSE(acint(1:na, 1:np, bi_zz)))
2066 :
2067 : ! +r_beta*Vnl*r_alpha
2068 : blocks_rv(1, 1)%block(1:nb, 1:na) = blocks_rv(1, 1)%block(1:nb, 1:na) + &
2069 : MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_x)))
2070 :
2071 : blocks_rv(1, 2)%block(1:nb, 1:na) = blocks_rv(1, 2)%block(1:nb, 1:na) + &
2072 : MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_x)))
2073 :
2074 : blocks_rv(1, 3)%block(1:nb, 1:na) = blocks_rv(1, 3)%block(1:nb, 1:na) + &
2075 : MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_x)))
2076 :
2077 : blocks_rv(2, 1)%block(1:nb, 1:na) = blocks_rv(2, 1)%block(1:nb, 1:na) + &
2078 : MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_y)))
2079 :
2080 : blocks_rv(2, 2)%block(1:nb, 1:na) = blocks_rv(2, 2)%block(1:nb, 1:na) + &
2081 : MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_y)))
2082 :
2083 : blocks_rv(2, 3)%block(1:nb, 1:na) = blocks_rv(2, 3)%block(1:nb, 1:na) + &
2084 : MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_y)))
2085 :
2086 : blocks_rv(3, 1)%block(1:nb, 1:na) = blocks_rv(3, 1)%block(1:nb, 1:na) + &
2087 : MATMUL(bchint(1:nb, 1:np, bi_x), TRANSPOSE(acint(1:na, 1:np, bi_z)))
2088 :
2089 : blocks_rv(3, 2)%block(1:nb, 1:na) = blocks_rv(3, 2)%block(1:nb, 1:na) + &
2090 : MATMUL(bchint(1:nb, 1:np, bi_y), TRANSPOSE(acint(1:na, 1:np, bi_z)))
2091 :
2092 : blocks_rv(3, 3)%block(1:nb, 1:na) = blocks_rv(3, 3)%block(1:nb, 1:na) + &
2093 : MATMUL(bchint(1:nb, 1:np, bi_z), TRANSPOSE(acint(1:na, 1:np, bi_z)))
2094 :
2095 : END IF
2096 : !$ CALL omp_unset_lock(locks(hash))
2097 : EXIT ! We have found a match and there can be only one single match
2098 : END IF
2099 : END DO
2100 : END DO
2101 : END DO
2102 : DO i = 1, 3
2103 : NULLIFY (blocks_rv(i, 1)%block)
2104 : NULLIFY (blocks_rv(i, 2)%block)
2105 : NULLIFY (blocks_rv(i, 3)%block)
2106 : END DO
2107 : END DO
2108 :
2109 : !$OMP DO
2110 : !$ DO lock_num = 1, nlock
2111 : !$ call omp_destroy_lock(locks(lock_num))
2112 : !$ END DO
2113 : !$OMP END DO
2114 :
2115 : !$OMP SINGLE
2116 : !$ DEALLOCATE (locks)
2117 : !$OMP END SINGLE NOWAIT
2118 :
2119 : !$OMP END PARALLEL
2120 :
2121 6 : CALL release_sap_int(sap_int)
2122 :
2123 6 : DEALLOCATE (basis_set)
2124 :
2125 6 : CALL timestop(handle)
2126 :
2127 18 : END SUBROUTINE build_dcom_rpnl
2128 :
2129 : ! **************************************************************************************************
2130 : !> \brief Calculate the product O*r or r*O from the integrals [a|O|b].
2131 : !> We assume that on input all integrals [a+1|O|b+1] are available.
2132 : !> \param la_max ...
2133 : !> \param npgfa ...
2134 : !> \param rpgfa ...
2135 : !> \param la_min ...
2136 : !> \param lb_max ...
2137 : !> \param npgfb ...
2138 : !> \param rpgfb ...
2139 : !> \param lb_min ...
2140 : !> \param dab ...
2141 : !> \param ab ...
2142 : !> \param comabr ...
2143 : !>
2144 : !> \param ra ...
2145 : !> \param rb ...
2146 : !> \param direction_Or ...
2147 : !> \par Literature
2148 : !> S. Obara and A. Saika, J. Chem. Phys. 84, 3963 (1986)
2149 : !> \par Parameters
2150 : !> - ax,ay,az : Angular momentum index numbers of orbital a.
2151 : !> - bx,by,bz : Angular momentum index numbers of orbital b.
2152 : !> - coset : Cartesian orbital set pointer.
2153 : !> - l{a,b} : Angular momentum quantum number of shell a or b.
2154 : !> - l{a,b}_max: Maximum angular momentum quantum number of shell a or b.
2155 : !> - l{a,b}_min: Minimum angular momentum quantum number of shell a or b.
2156 : !> - ncoset : Number of orbitals in a Cartesian orbital set.
2157 : !> - npgf{a,b} : Degree of contraction of shell a or b.
2158 : !> - rab : Distance vector between the atomic centers a and b.
2159 : !> - rab2 : Square of the distance between the atomic centers a and b.
2160 : !> - rac : Distance vector between the atomic centers a and c.
2161 : !> - rac2 : Square of the distance between the atomic centers a and c.
2162 : !> - rbc : Distance vector between the atomic centers b and c.
2163 : !> - rbc2 : Square of the distance between the atomic centers b and c.
2164 : !> - rpgf{a,b} : Radius of the primitive Gaussian-type function a or b.
2165 : !> - zet{a,b} : Exponents of the Gaussian-type functions a or b.
2166 : !> - zetp : Reciprocal of the sum of the exponents of orbital a and b.
2167 : !>
2168 : !> \author Tomas Zimmermann
2169 : ! **************************************************************************************************
2170 1197 : SUBROUTINE ab_opr(la_max, npgfa, rpgfa, la_min, lb_max, npgfb, rpgfb, lb_min, &
2171 2394 : dab, ab, comabr, ra, rb, direction_Or)
2172 : INTEGER, INTENT(IN) :: la_max, npgfa
2173 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: rpgfa
2174 : INTEGER, INTENT(IN) :: la_min, lb_max, npgfb
2175 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: rpgfb
2176 : INTEGER, INTENT(IN) :: lb_min
2177 : REAL(KIND=dp), INTENT(IN) :: dab
2178 : REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: ab
2179 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT) :: comabr
2180 : REAL(KIND=dp), DIMENSION(1:3), INTENT(IN) :: ra, rb
2181 : LOGICAL :: direction_Or
2182 :
2183 : INTEGER :: ax, ay, az, bx, by, bz, coa, coap, &
2184 : coapx, coapy, coapz, cob, cobp, cobpx, &
2185 : cobpy, cobpz, ipgf, jpgf, la, lb, na, &
2186 : nap, nb, nbp, ofa, ofb
2187 :
2188 41611140 : comabr = 0.0_dp
2189 :
2190 1197 : ofa = ncoset(la_min - 1)
2191 1197 : ofb = ncoset(lb_min - 1)
2192 :
2193 1197 : na = 0
2194 1197 : nap = 0
2195 5985 : DO ipgf = 1, npgfa
2196 4788 : nb = 0
2197 4788 : nbp = 0
2198 23940 : DO jpgf = 1, npgfb
2199 19152 : IF (rpgfa(ipgf) + rpgfb(jpgf) > dab) THEN
2200 45106 : DO la = la_min, la_max
2201 78603 : DO ax = 0, la
2202 100491 : DO ay = 0, la - ax
2203 40793 : az = la - ax - ay
2204 40793 : coa = na + coset(ax, ay, az) - ofa
2205 40793 : coap = nap + coset(ax, ay, az) - ofa
2206 40793 : coapx = nap + coset(ax + 1, ay, az) - ofa
2207 40793 : coapy = nap + coset(ax, ay + 1, az) - ofa
2208 40793 : coapz = nap + coset(ax, ay, az + 1) - ofa
2209 127851 : DO lb = lb_min, lb_max
2210 160683 : DO bx = 0, lb
2211 198987 : DO by = 0, lb - bx
2212 79097 : bz = lb - bx - by
2213 79097 : cob = nb + coset(bx, by, bz) - ofb
2214 79097 : cobp = nbp + coset(bx, by, bz) - ofb
2215 79097 : cobpx = nbp + coset(bx + 1, by, bz) - ofb
2216 79097 : cobpy = nbp + coset(bx, by + 1, bz) - ofb
2217 79097 : cobpz = nbp + coset(bx, by, bz + 1) - ofb
2218 145426 : IF (direction_Or) THEN
2219 : ! [a|O * x|b] = [a|O|b(x+1)] + [a|O|b] * X_b
2220 : ! = [a|O * (x - X_b)|b] + [a|O|b] * X_b
2221 : ! So the second term makes sure that we actually calculate
2222 : ! <O*r> and not <O*(r-R)>
2223 15409 : comabr(coa, cob, 1) = ab(coap, cobpx) + ab(coap, cobp)*rb(1)
2224 15409 : comabr(coa, cob, 2) = ab(coap, cobpy) + ab(coap, cobp)*rb(2)
2225 15409 : comabr(coa, cob, 3) = ab(coap, cobpz) + ab(coap, cobp)*rb(3)
2226 : ELSE
2227 63688 : comabr(coa, cob, 1) = ab(coapx, cobp) + ab(coap, cobp)*ra(1)
2228 63688 : comabr(coa, cob, 2) = ab(coapy, cobp) + ab(coap, cobp)*ra(2)
2229 63688 : comabr(coa, cob, 3) = ab(coapz, cobp) + ab(coap, cobp)*ra(3)
2230 : END IF
2231 : END DO
2232 : END DO
2233 : END DO
2234 : END DO
2235 : END DO
2236 : END DO
2237 : END IF
2238 19152 : nb = nb + ncoset(lb_max) - ofb
2239 23940 : nbp = nbp + ncoset(lb_max + 1) - ofb
2240 : END DO
2241 4788 : na = na + ncoset(la_max) - ofa
2242 5985 : nap = nap + ncoset(la_max + 1) - ofa
2243 : END DO
2244 :
2245 1197 : END SUBROUTINE ab_opr
2246 :
2247 : ! **************************************************************************************************
2248 : !> \brief Apply the operator \delta_\mu^\lambda to zero out all elements of the matrix
2249 : !> which don't fulfill the condition.
2250 : !> Operates on matrix_hr(1:3) instead of a single matrix
2251 : !> \param matrix_hr ...
2252 : !> \param qs_kind_set ...
2253 : !> \param basis_type ...
2254 : !> \param sab_nl ...
2255 : !> \param deltaR ...
2256 : !> \param direction_Or ...
2257 : !> \author Edward Ditler
2258 : ! **************************************************************************************************
2259 18 : SUBROUTINE hr_mult_by_delta_3d(matrix_hr, qs_kind_set, basis_type, sab_nl, deltaR, direction_Or)
2260 :
2261 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_hr
2262 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
2263 : CHARACTER(LEN=*), INTENT(IN) :: basis_type
2264 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2265 : POINTER :: sab_nl
2266 : REAL(KIND=dp), DIMENSION(:, :) :: deltaR
2267 : LOGICAL :: direction_Or
2268 :
2269 : CHARACTER(len=*), PARAMETER :: routineN = 'hr_mult_by_delta_3d'
2270 :
2271 : INTEGER :: handle, iatom, icol, ikind, ir, irow, &
2272 : jatom, jkind, ldsab, mepos, nkind, &
2273 : nseta, nsetb, nthread
2274 : INTEGER, DIMENSION(3) :: cell
2275 18 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, npgfa, &
2276 18 : npgfb, nsgfa, nsgfb
2277 18 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
2278 : LOGICAL :: do_symmetric, found
2279 : REAL(KIND=dp), DIMENSION(3) :: rab
2280 18 : REAL(KIND=dp), DIMENSION(:), POINTER :: set_radius_a, set_radius_b
2281 18 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: kx_block, ky_block, kz_block, rpgfa, &
2282 18 : rpgfb, scon_a, scon_b, sphi_a, sphi_b, &
2283 18 : zeta, zetb
2284 18 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
2285 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
2286 : TYPE(neighbor_list_iterator_p_type), &
2287 18 : DIMENSION(:), POINTER :: nl_iterator
2288 :
2289 18 : CALL timeset(routineN, handle)
2290 :
2291 18 : nkind = SIZE(qs_kind_set)
2292 :
2293 : ! check for symmetry
2294 18 : CPASSERT(SIZE(sab_nl) > 0)
2295 18 : CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
2296 :
2297 : ! prepare basis set
2298 90 : ALLOCATE (basis_set_list(nkind))
2299 18 : CALL basis_set_list_setup(basis_set_list, basis_type, qs_kind_set)
2300 :
2301 : ! *** Allocate work storage ***
2302 18 : ldsab = get_memory_usage(qs_kind_set, basis_type)
2303 :
2304 : nthread = 1
2305 18 : !$ nthread = omp_get_max_threads()
2306 : ! Iterate of neighbor list
2307 18 : CALL neighbor_list_iterator_create(nl_iterator, sab_nl, nthread=nthread)
2308 :
2309 : !$OMP PARALLEL DEFAULT(NONE) &
2310 : !$OMP SHARED (nthread,ldsab,nl_iterator, do_symmetric) &
2311 : !$OMP SHARED (ncoset,matrix_hr,basis_set_list) &
2312 : !$OMP SHARED (direction_or, deltar) &
2313 : !$OMP PRIVATE (kx_block,ky_block,kz_block,mepos,ikind,jkind,iatom,jatom,rab,cell) &
2314 : !$OMP PRIVATE (basis_set_a,basis_set_b) &
2315 : !$OMP PRIVATE (nseta, nsetb) &
2316 : !$OMP PRIVATE (first_sgfa, la_max, la_min, npgfa, nsgfa, rpgfa, set_radius_a, sphi_a, zeta, scon_a) &
2317 : !$OMP PRIVATE (first_sgfb, lb_max, lb_min, npgfb, nsgfb, rpgfb, set_radius_b, sphi_b, zetb, scon_b) &
2318 18 : !$OMP PRIVATE (irow, icol, found)
2319 :
2320 : mepos = 0
2321 : !$ mepos = omp_get_thread_num()
2322 :
2323 : DO WHILE (neighbor_list_iterate(nl_iterator, mepos=mepos) == 0)
2324 : CALL get_iterator_info(nl_iterator, mepos=mepos, ikind=ikind, jkind=jkind, &
2325 : iatom=iatom, jatom=jatom, r=rab, cell=cell)
2326 : basis_set_a => basis_set_list(ikind)%gto_basis_set
2327 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
2328 : basis_set_b => basis_set_list(jkind)%gto_basis_set
2329 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
2330 : ! basis ikind
2331 : first_sgfa => basis_set_a%first_sgf
2332 : la_max => basis_set_a%lmax
2333 : la_min => basis_set_a%lmin
2334 : npgfa => basis_set_a%npgf
2335 : nsgfa => basis_set_a%nsgf_set
2336 : rpgfa => basis_set_a%pgf_radius
2337 : set_radius_a => basis_set_a%set_radius
2338 : sphi_a => basis_set_a%sphi
2339 : zeta => basis_set_a%zet
2340 : scon_a => basis_set_a%scon
2341 : ! basis jkind
2342 : first_sgfb => basis_set_b%first_sgf
2343 : lb_max => basis_set_b%lmax
2344 : lb_min => basis_set_b%lmin
2345 : npgfb => basis_set_b%npgf
2346 : nsgfb => basis_set_b%nsgf_set
2347 : rpgfb => basis_set_b%pgf_radius
2348 : set_radius_b => basis_set_b%set_radius
2349 : sphi_b => basis_set_b%sphi
2350 : zetb => basis_set_b%zet
2351 : scon_b => basis_set_b%scon
2352 :
2353 : nseta = basis_set_a%nset
2354 : nsetb = basis_set_b%nset
2355 :
2356 : IF (do_symmetric) THEN
2357 : IF (iatom <= jatom) THEN
2358 : irow = iatom
2359 : icol = jatom
2360 : ELSE
2361 : irow = jatom
2362 : icol = iatom
2363 : END IF
2364 : ELSE
2365 : irow = iatom
2366 : icol = jatom
2367 : END IF
2368 :
2369 : NULLIFY (kx_block, ky_block, kz_block)
2370 : CALL dbcsr_get_block_p(matrix_hr(1)%matrix, irow, icol, kx_block, found)
2371 : CPASSERT(found)
2372 : CALL dbcsr_get_block_p(matrix_hr(2)%matrix, irow, icol, ky_block, found)
2373 : CPASSERT(found)
2374 : CALL dbcsr_get_block_p(matrix_hr(3)%matrix, irow, icol, kz_block, found)
2375 : CPASSERT(found)
2376 :
2377 : IF (direction_Or) THEN
2378 : DO ir = 1, 3
2379 : !$OMP CRITICAL(blockadd)
2380 : SELECT CASE (ir)
2381 : CASE (1)
2382 : kx_block(:, :) = kx_block(:, :)*deltaR(ir, jatom)
2383 : CASE (2)
2384 : ky_block(:, :) = ky_block(:, :)*deltaR(ir, jatom)
2385 : CASE (3)
2386 : kz_block(:, :) = kz_block(:, :)*deltaR(ir, jatom)
2387 : END SELECT
2388 : !$OMP END CRITICAL(blockadd)
2389 : END DO
2390 : ELSE
2391 : DO ir = 1, 3
2392 : !$OMP CRITICAL(blockadd)
2393 : SELECT CASE (ir)
2394 : CASE (1)
2395 : kx_block(:, :) = kx_block(:, :)*deltaR(ir, iatom)
2396 : CASE (2)
2397 : ky_block(:, :) = ky_block(:, :)*deltaR(ir, iatom)
2398 : CASE (3)
2399 : kz_block(:, :) = kz_block(:, :)*deltaR(ir, iatom)
2400 : END SELECT
2401 : !$OMP END CRITICAL(blockadd)
2402 : END DO
2403 : END IF
2404 : END DO
2405 : !$OMP END PARALLEL
2406 18 : CALL neighbor_list_iterator_release(nl_iterator)
2407 :
2408 : ! Release work storage
2409 18 : DEALLOCATE (basis_set_list)
2410 :
2411 18 : CALL timestop(handle)
2412 :
2413 36 : END SUBROUTINE hr_mult_by_delta_3d
2414 :
2415 1026 : END MODULE qs_vcd_ao
|