Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 : ! **************************************************************************************************
8 : !> \brief Calculation of the local pseudopotential contribution to the core Hamiltonian
9 : !> <a|V(local)|b> = <a|Sum e^a*rc**2|b>
10 : !> \par History
11 : !> - core_ppnl refactored from qs_core_hamiltonian [Joost VandeVondele, 2008-11-01]
12 : !> - adapted for PPL [jhu, 2009-02-23]
13 : !> - OpenMP added [Iain Bethune, Fiona Reid, 2013-11-13]
14 : !> - Bug fix: correct orbital pointer range [07.2014,JGH]
15 : !> - k-point aware [07.2015,JGH]
16 : !> - Extended by the derivatives for DFPT [Sandra Luber, Edward Ditler, 2021]
17 : ! **************************************************************************************************
18 : MODULE core_ppl
19 :
20 : USE ai_overlap_ppl, ONLY: ecploc_integral,&
21 : ppl_integral,&
22 : ppl_integral_ri
23 : USE atomic_kind_types, ONLY: atomic_kind_type,&
24 : get_atomic_kind_set
25 : USE basis_set_types, ONLY: gto_basis_set_p_type,&
26 : gto_basis_set_type
27 : USE cp_dbcsr_api, ONLY: dbcsr_add,&
28 : dbcsr_get_block_p,&
29 : dbcsr_p_type
30 : USE external_potential_types, ONLY: get_potential,&
31 : gth_potential_type,&
32 : sgp_potential_type
33 : USE kinds, ONLY: dp,&
34 : int_8
35 : USE libgrpp_integrals, ONLY: libgrpp_local_forces_ref,&
36 : libgrpp_local_integrals,&
37 : libgrpp_semilocal_forces_ref,&
38 : libgrpp_semilocal_integrals
39 : USE lri_environment_types, ONLY: lri_kind_type
40 : USE orbital_pointers, ONLY: init_orbital_pointers,&
41 : ncoset
42 : USE particle_types, ONLY: particle_type
43 : USE qs_force_types, ONLY: qs_force_type
44 : USE qs_kind_types, ONLY: get_qs_kind,&
45 : get_qs_kind_set,&
46 : qs_kind_type
47 : USE qs_neighbor_list_types, ONLY: get_iterator_info,&
48 : neighbor_list_iterator_create,&
49 : neighbor_list_iterator_p_type,&
50 : neighbor_list_iterator_release,&
51 : neighbor_list_set_p_type,&
52 : nl_set_sub_iterator,&
53 : nl_sub_iterate
54 : USE upf_local_integrals, ONLY: upf_local_init,&
55 : upf_local_matrix,&
56 : upf_local_ri
57 : USE virial_methods, ONLY: virial_pair_force
58 : USE virial_types, ONLY: virial_type
59 :
60 : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num, omp_get_num_threads
61 : !$ USE OMP_LIB, ONLY: omp_lock_kind, &
62 : !$ omp_init_lock, omp_set_lock, &
63 : !$ omp_unset_lock, omp_destroy_lock
64 :
65 : #include "./base/base_uses.f90"
66 :
67 : IMPLICIT NONE
68 :
69 : PRIVATE
70 :
71 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'core_ppl'
72 :
73 : PUBLIC :: build_core_ppl, build_core_ppl_ri
74 :
75 : CONTAINS
76 :
77 : ! **************************************************************************************************
78 : !> \brief ...
79 : !> \param matrix_h ...
80 : !> \param matrix_p ...
81 : !> \param force ...
82 : !> \param virial ...
83 : !> \param calculate_forces ...
84 : !> \param use_virial ...
85 : !> \param nder ...
86 : !> \param qs_kind_set ...
87 : !> \param atomic_kind_set ...
88 : !> \param particle_set ...
89 : !> \param sab_orb ...
90 : !> \param sac_ppl ...
91 : !> \param nimages ...
92 : !> \param cell_to_index ...
93 : !> \param basis_type ...
94 : !> \param deltaR Weighting factors of the derivatives wrt. nuclear positions
95 : !> \param atcore ...
96 : ! **************************************************************************************************
97 21070 : SUBROUTINE build_core_ppl(matrix_h, matrix_p, force, virial, calculate_forces, use_virial, nder, &
98 : qs_kind_set, atomic_kind_set, particle_set, sab_orb, sac_ppl, &
99 21070 : nimages, cell_to_index, basis_type, deltaR, atcore)
100 :
101 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_h, matrix_p
102 : TYPE(qs_force_type), DIMENSION(:), POINTER :: force
103 : TYPE(virial_type), POINTER :: virial
104 : LOGICAL, INTENT(IN) :: calculate_forces
105 : LOGICAL :: use_virial
106 : INTEGER :: nder
107 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
108 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
109 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
110 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
111 : POINTER :: sab_orb, sac_ppl
112 : INTEGER, INTENT(IN) :: nimages
113 : INTEGER, DIMENSION(:, :, :), OPTIONAL, POINTER :: cell_to_index
114 : CHARACTER(LEN=*), INTENT(IN) :: basis_type
115 : REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
116 : OPTIONAL :: deltaR
117 : REAL(KIND=dp), DIMENSION(:), INTENT(INOUT), &
118 : OPTIONAL :: atcore
119 :
120 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_core_ppl'
121 : INTEGER, PARAMETER :: nexp_max = 30
122 :
123 : INTEGER :: atom_a, handle, i, iatom, icol, ikind, img, irow, iset, jatom, jkind, jset, &
124 : katom, kkind, ldai, ldsab, maxco, maxder, maxl, maxlgto, maxlppl, maxnset, maxsgf, mepos, &
125 : n_local, natom, ncoa, ncob, nexp_lpot, nexp_ppl, nkind, nloc, nseta, nsetb, nthread, &
126 : sgfa, sgfb, slmax, slot
127 21070 : INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, kind_of
128 : INTEGER, DIMENSION(0:10) :: npot
129 : INTEGER, DIMENSION(1:10) :: nrloc
130 : INTEGER, DIMENSION(1:15, 0:10) :: nrpot
131 : INTEGER, DIMENSION(3) :: cellind
132 21070 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, &
133 21070 : nct_lpot, npgfa, npgfb, nsgfa, nsgfb
134 21070 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
135 : INTEGER, DIMENSION(nexp_max) :: nct_ppl
136 : LOGICAL :: do_dR, do_upf, doat, dokp, ecp_local, &
137 : ecp_semi_local, found, have_upf, &
138 : libgrpp_local, lpotextended, &
139 : only_gaussians
140 : REAL(KIND=dp) :: alpha, atk0, atk1, dab, dac, dbc, f0, &
141 : ppl_radius
142 21070 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: upf_v, work
143 21070 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: hab2_w, ppl_fwork, ppl_work, upf_da, &
144 21070 : upf_db
145 21070 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: hab, pab
146 : REAL(KIND=dp), ALLOCATABLE, &
147 21070 : DIMENSION(:, :, :, :, :) :: hab2
148 : REAL(KIND=dp), DIMENSION(1:10) :: aloc, bloc
149 : REAL(KIND=dp), DIMENSION(1:15, 0:10) :: apot, bpot
150 : REAL(KIND=dp), DIMENSION(3) :: force_a, force_b, rab, rac, rbc
151 : REAL(KIND=dp), DIMENSION(3, 3) :: pv_thread
152 : TYPE(neighbor_list_iterator_p_type), &
153 21070 : DIMENSION(:), POINTER :: ap_iterator
154 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
155 21070 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
156 : TYPE(gth_potential_type), POINTER :: gth_potential
157 42140 : REAL(KIND=dp), DIMENSION(SIZE(particle_set)) :: at_thread
158 : REAL(KIND=dp), DIMENSION(nexp_max) :: alpha_ppl
159 21070 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: cval_lpot, h1_1block, h1_2block, &
160 21070 : h1_3block, h_block, p_block, rpgfa, &
161 21070 : rpgfb, sphi_a, sphi_b, zeta, zetb
162 21070 : REAL(KIND=dp), DIMENSION(:), POINTER :: a_local, alpha_lpot, c_local, cexp_ppl, &
163 21070 : set_radius_a, set_radius_b
164 : REAL(KIND=dp), DIMENSION(4, nexp_max) :: cval_ppl
165 42140 : REAL(KIND=dp), DIMENSION(3, SIZE(particle_set)) :: force_thread
166 : TYPE(sgp_potential_type), POINTER :: sgp_potential
167 :
168 : !$ INTEGER(kind=omp_lock_kind), &
169 21070 : !$ ALLOCATABLE, DIMENSION(:) :: locks
170 : !$ INTEGER :: lock_num, hash, hash1, hash2
171 : !$ INTEGER(KIND=int_8) :: iatom8
172 : !$ INTEGER, PARAMETER :: nlock = 501
173 :
174 21070 : do_dR = PRESENT(deltaR)
175 21070 : doat = PRESENT(atcore)
176 21070 : IF ((calculate_forces .OR. doat) .AND. do_dR) THEN
177 0 : CPABORT("core_ppl: incompatible options")
178 : END IF
179 :
180 : MARK_USED(int_8)
181 :
182 : ! Use internal integral routine for local ECP terms or use libgrrp
183 21070 : libgrpp_local = .FALSE.
184 :
185 21070 : IF (calculate_forces) THEN
186 7977 : CALL timeset(routineN//"_forces", handle)
187 : ELSE
188 13093 : CALL timeset(routineN, handle)
189 : END IF
190 :
191 21070 : nkind = SIZE(atomic_kind_set)
192 21070 : natom = SIZE(particle_set)
193 :
194 21070 : dokp = (nimages > 1)
195 :
196 21070 : IF (dokp) THEN
197 1272 : IF (PRESENT(cell_to_index)) THEN
198 1272 : CPASSERT(ASSOCIATED(cell_to_index))
199 : ELSE
200 0 : CPABORT("Missing cell_to_index for k-point calculation")
201 : END IF
202 : END IF
203 :
204 21070 : IF (calculate_forces .OR. doat) THEN
205 8039 : IF (SIZE(matrix_p, 1) == 2) THEN
206 3734 : DO img = 1, nimages
207 : CALL dbcsr_add(matrix_p(1, img)%matrix, matrix_p(2, img)%matrix, &
208 2750 : alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
209 : CALL dbcsr_add(matrix_p(2, img)%matrix, matrix_p(1, img)%matrix, &
210 3734 : alpha_scalar=-2.0_dp, beta_scalar=1.0_dp)
211 : END DO
212 : END IF
213 : END IF
214 331030 : force_thread = 0.0_dp
215 98560 : at_thread = 0.0_dp
216 :
217 21070 : maxder = ncoset(nder)
218 :
219 : CALL get_qs_kind_set(qs_kind_set, maxco=maxco, maxlgto=maxlgto, &
220 : maxsgf=maxsgf, maxnset=maxnset, maxlppl=maxlppl, &
221 21070 : basis_type=basis_type)
222 :
223 21070 : maxl = MAX(maxlgto, maxlppl)
224 21070 : CALL init_orbital_pointers(2*maxl + 2*nder + 1)
225 :
226 21070 : ldsab = MAX(maxco, ncoset(maxlppl), maxsgf, maxlppl)
227 21070 : ldai = ncoset(maxl + nder + 1)
228 :
229 100011 : ALLOCATE (basis_set_list(nkind))
230 57871 : DO ikind = 1, nkind
231 36801 : CALL get_qs_kind(qs_kind_set(ikind), basis_set=basis_set_a, basis_type=basis_type)
232 57871 : IF (ASSOCIATED(basis_set_a)) THEN
233 36801 : basis_set_list(ikind)%gto_basis_set => basis_set_a
234 : ELSE
235 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
236 : END IF
237 : END DO
238 :
239 21070 : CALL prepare_upf_local(qs_kind_set, 2*maxlgto + 1, have_upf)
240 :
241 21070 : pv_thread = 0.0_dp
242 :
243 : nthread = 1
244 21070 : !$ nthread = omp_get_max_threads()
245 :
246 : ! iterator for basis/potential list
247 21070 : CALL neighbor_list_iterator_create(ap_iterator, sac_ppl, search=.TRUE., nthread=nthread)
248 :
249 : !$OMP PARALLEL &
250 : !$OMP DEFAULT (NONE) &
251 : !$OMP SHARED (ap_iterator, basis_set_list, calculate_forces, use_virial, &
252 : !$OMP matrix_h, matrix_p, atomic_kind_set, qs_kind_set, particle_set, &
253 : !$OMP sab_orb, sac_ppl, nthread, ncoset, nkind, cell_to_index, &
254 : !$OMP ldsab, maxnset, maxder, do_dR, deltaR, doat, libgrpp_local, &
255 : !$OMP maxlgto, nder, maxco, dokp, locks, natom, have_upf) &
256 : !$OMP PRIVATE (ikind, jkind, iatom, jatom, rab, basis_set_a, basis_set_b, &
257 : !$OMP first_sgfa, la_max, la_min, npgfa, nsgfa, sphi_a, &
258 : !$OMP zeta, first_sgfb, lb_max, lb_min, npgfb, nsetb, rpgfb, set_radius_b, sphi_b, &
259 : !$OMP zetb, dab, irow, icol, h_block, found, iset, ncoa, lock_num, &
260 : !$OMP sgfa, jset, ncob, sgfb, nsgfb, p_block, work, pab, hab, hab2, hab2_w, &
261 : !$OMP atk0, atk1, h1_1block, h1_2block, h1_3block, kkind, nseta, &
262 : !$OMP gth_potential, sgp_potential, alpha, cexp_ppl, lpotextended, &
263 : !$OMP ppl_radius, nexp_lpot, nexp_ppl, alpha_ppl, alpha_lpot, nct_ppl, &
264 : !$OMP nct_lpot, cval_ppl, cval_lpot, rac, dac, rbc, dbc, &
265 : !$OMP set_radius_a, rpgfa, force_a, force_b, ppl_fwork, mepos, &
266 : !$OMP slot, f0, katom, ppl_work, cellind, img, ecp_local, ecp_semi_local, &
267 : !$OMP nloc, nrloc, aloc, bloc, n_local, a_local, c_local, &
268 : !$OMP slmax, npot, nrpot, apot, bpot, only_gaussians, &
269 : !$OMP ldai, hash, hash1, hash2, iatom8, do_upf, upf_v, upf_da, upf_db) &
270 21070 : !$OMP REDUCTION (+ : pv_thread, force_thread, at_thread )
271 :
272 : !$OMP SINGLE
273 : !$ ALLOCATE (locks(nlock))
274 : !$OMP END SINGLE
275 :
276 : !$OMP DO
277 : !$ DO lock_num = 1, nlock
278 : !$ call omp_init_lock(locks(lock_num))
279 : !$ END DO
280 : !$OMP END DO
281 :
282 : mepos = 0
283 : !$ mepos = omp_get_thread_num()
284 :
285 : ALLOCATE (hab(ldsab, ldsab, maxnset, maxnset), work(ldsab, ldsab*maxder))
286 : IF (have_upf) THEN
287 : ALLOCATE (upf_v(ldsab, ldsab))
288 : IF (calculate_forces .OR. do_dR) ALLOCATE (upf_da(ldsab, ldsab, 3), upf_db(ldsab, ldsab, 3))
289 : END IF
290 : ldai = ncoset(2*maxlgto + 2*nder)
291 : ALLOCATE (ppl_work(ldai, ldai, MAX(maxder, 2*maxlgto + 2*nder + 1)))
292 : IF (calculate_forces .OR. doat) THEN
293 : ALLOCATE (pab(maxco, maxco, maxnset, maxnset))
294 : ldai = ncoset(maxlgto)
295 : ALLOCATE (ppl_fwork(ldai, ldai, maxder))
296 : END IF
297 :
298 : !$OMP DO SCHEDULE(GUIDED)
299 : DO slot = 1, sab_orb(1)%nl_size
300 : !SL
301 : IF (do_dR) THEN
302 : ALLOCATE (hab2(ldsab, ldsab, 4, maxnset, maxnset))
303 : ALLOCATE (hab2_w(ldsab, ldsab, 6))
304 : ALLOCATE (ppl_fwork(ldai, ldai, maxder))
305 : END IF
306 :
307 : ikind = sab_orb(1)%nlist_task(slot)%ikind
308 : jkind = sab_orb(1)%nlist_task(slot)%jkind
309 : iatom = sab_orb(1)%nlist_task(slot)%iatom
310 : jatom = sab_orb(1)%nlist_task(slot)%jatom
311 : cellind(:) = sab_orb(1)%nlist_task(slot)%cell(:)
312 : rab(1:3) = sab_orb(1)%nlist_task(slot)%r(1:3)
313 :
314 : basis_set_a => basis_set_list(ikind)%gto_basis_set
315 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
316 : basis_set_b => basis_set_list(jkind)%gto_basis_set
317 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
318 :
319 : !$ iatom8 = INT(iatom - 1, int_8)*INT(natom, int_8) + INT(jatom, int_8)
320 : !$ hash1 = INT(MOD(iatom8, INT(nlock, int_8)) + 1)
321 :
322 : ! basis ikind
323 : first_sgfa => basis_set_a%first_sgf
324 : la_max => basis_set_a%lmax
325 : la_min => basis_set_a%lmin
326 : npgfa => basis_set_a%npgf
327 : nseta = basis_set_a%nset
328 : nsgfa => basis_set_a%nsgf_set
329 : rpgfa => basis_set_a%pgf_radius
330 : set_radius_a => basis_set_a%set_radius
331 : sphi_a => basis_set_a%sphi
332 : zeta => basis_set_a%zet
333 : ! basis jkind
334 : first_sgfb => basis_set_b%first_sgf
335 : lb_max => basis_set_b%lmax
336 : lb_min => basis_set_b%lmin
337 : npgfb => basis_set_b%npgf
338 : nsetb = basis_set_b%nset
339 : nsgfb => basis_set_b%nsgf_set
340 : rpgfb => basis_set_b%pgf_radius
341 : set_radius_b => basis_set_b%set_radius
342 : sphi_b => basis_set_b%sphi
343 : zetb => basis_set_b%zet
344 :
345 : dab = SQRT(SUM(rab*rab))
346 :
347 : IF (dokp) THEN
348 : img = cell_to_index(cellind(1), cellind(2), cellind(3))
349 : ELSE
350 : img = 1
351 : END IF
352 :
353 : ! *** Use the symmetry of the first derivatives ***
354 : IF (iatom == jatom) THEN
355 : f0 = 1.0_dp
356 : ELSE
357 : f0 = 2.0_dp
358 : END IF
359 :
360 : ! *** Create matrix blocks for a new matrix block column ***
361 : IF (iatom <= jatom) THEN
362 : irow = iatom
363 : icol = jatom
364 : ELSE
365 : irow = jatom
366 : icol = iatom
367 : END IF
368 : NULLIFY (h_block)
369 :
370 : IF (do_dR) THEN
371 : NULLIFY (h1_1block, h1_2block, h1_3block)
372 :
373 : CALL dbcsr_get_block_p(matrix=matrix_h(1, img)%matrix, &
374 : row=irow, col=icol, BLOCK=h1_1block, found=found)
375 : CALL dbcsr_get_block_p(matrix=matrix_h(2, img)%matrix, &
376 : row=irow, col=icol, BLOCK=h1_2block, found=found)
377 : CALL dbcsr_get_block_p(matrix=matrix_h(3, img)%matrix, &
378 : row=irow, col=icol, BLOCK=h1_3block, found=found)
379 : END IF
380 :
381 : CALL dbcsr_get_block_p(matrix_h(1, img)%matrix, irow, icol, h_block, found)
382 : CPASSERT(found)
383 : IF (calculate_forces .OR. doat) THEN
384 : NULLIFY (p_block)
385 : CALL dbcsr_get_block_p(matrix_p(1, img)%matrix, irow, icol, p_block, found)
386 : IF (ASSOCIATED(p_block)) THEN
387 : DO iset = 1, nseta
388 : ncoa = npgfa(iset)*ncoset(la_max(iset))
389 : sgfa = first_sgfa(1, iset)
390 : DO jset = 1, nsetb
391 : ncob = npgfb(jset)*ncoset(lb_max(jset))
392 : sgfb = first_sgfb(1, jset)
393 :
394 : ! *** Decontract density matrix block ***
395 : IF (iatom <= jatom) THEN
396 : work(1:ncoa, 1:nsgfb(jset)) = MATMUL(sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1), &
397 : p_block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1))
398 : ELSE
399 : work(1:ncoa, 1:nsgfb(jset)) = MATMUL(sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1), &
400 : TRANSPOSE(p_block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1)))
401 : END IF
402 :
403 : pab(1:ncoa, 1:ncob, iset, jset) = MATMUL(work(1:ncoa, 1:nsgfb(jset)), &
404 : TRANSPOSE(sphi_b(1:ncob, sgfb:sgfb + nsgfb(jset) - 1)))
405 : END DO
406 : END DO
407 : END IF
408 : END IF
409 :
410 : hab = 0._dp
411 : IF (do_dr) hab2 = 0._dp
412 :
413 : ! loop over all kinds for pseudopotential atoms
414 : DO kkind = 1, nkind
415 :
416 : CALL get_qs_kind(qs_kind_set(kkind), gth_potential=gth_potential, &
417 : sgp_potential=sgp_potential)
418 : ecp_semi_local = .FALSE.
419 : do_upf = .FALSE.
420 : only_gaussians = .TRUE.
421 : IF (ASSOCIATED(gth_potential)) THEN
422 : CALL get_potential(potential=gth_potential, &
423 : alpha_ppl=alpha, cexp_ppl=cexp_ppl, &
424 : lpot_present=lpotextended, ppl_radius=ppl_radius)
425 : nexp_ppl = 1
426 : alpha_ppl(1) = alpha
427 : nct_ppl(1) = SIZE(cexp_ppl)
428 : cval_ppl(1:nct_ppl(1), 1) = cexp_ppl(1:nct_ppl(1))
429 : IF (lpotextended) THEN
430 : CALL get_potential(potential=gth_potential, &
431 : nexp_lpot=nexp_lpot, alpha_lpot=alpha_lpot, nct_lpot=nct_lpot, &
432 : cval_lpot=cval_lpot)
433 : CPASSERT(nexp_lpot < nexp_max)
434 : nexp_ppl = nexp_lpot + 1
435 : alpha_ppl(2:nexp_lpot + 1) = alpha_lpot(1:nexp_lpot)
436 : nct_ppl(2:nexp_lpot + 1) = nct_lpot(1:nexp_lpot)
437 : DO i = 1, nexp_lpot
438 : cval_ppl(1:nct_lpot(i), i + 1) = cval_lpot(1:nct_lpot(i), i)
439 : END DO
440 : END IF
441 : ELSE IF (ASSOCIATED(sgp_potential)) THEN
442 : CALL get_potential(potential=sgp_potential, ecp_local=ecp_local, ecp_semi_local=ecp_semi_local, &
443 : ppl_radius=ppl_radius)
444 : do_upf = ALLOCATED(sgp_potential%upf_data)
445 : IF (do_upf) THEN
446 : CPASSERT(.NOT. ecp_local .AND. .NOT. ecp_semi_local)
447 : ELSE IF (ecp_local) THEN
448 : CALL get_potential(potential=sgp_potential, nloc=nloc, nrloc=nrloc, aloc=aloc, bloc=bloc)
449 : nexp_ppl = nloc
450 : CPASSERT(nexp_ppl <= nexp_max)
451 : nct_ppl(1:nloc) = nrloc(1:nloc)
452 : alpha_ppl(1:nloc) = bloc(1:nloc)
453 : cval_ppl(1, 1:nloc) = aloc(1:nloc)
454 : only_gaussians = .FALSE.
455 : ELSE
456 : CALL get_potential(potential=sgp_potential, n_local=n_local, a_local=a_local, c_local=c_local)
457 : nexp_ppl = n_local
458 : CPASSERT(nexp_ppl <= nexp_max)
459 : nct_ppl(1:n_local) = 1
460 : alpha_ppl(1:n_local) = a_local(1:n_local)
461 : cval_ppl(1, 1:n_local) = c_local(1:n_local)
462 : END IF
463 : IF (ecp_semi_local) THEN
464 : CALL get_potential(potential=sgp_potential, sl_lmax=slmax, &
465 : npot=npot, nrpot=nrpot, apot=apot, bpot=bpot)
466 : ELSE IF (ecp_local) THEN
467 : IF (SUM(ABS(aloc(1:nloc))) < 1.0e-12_dp) CYCLE
468 : END IF
469 : ELSE
470 : CYCLE
471 : END IF
472 :
473 : CALL nl_set_sub_iterator(ap_iterator, ikind, kkind, iatom, mepos=mepos)
474 :
475 : DO WHILE (nl_sub_iterate(ap_iterator, mepos=mepos) == 0)
476 :
477 : CALL get_iterator_info(ap_iterator, mepos=mepos, jatom=katom, r=rac)
478 :
479 : dac = SQRT(SUM(rac*rac))
480 : rbc(:) = rac(:) - rab(:)
481 : dbc = SQRT(SUM(rbc*rbc))
482 : IF ((MAXVAL(set_radius_a(:)) + ppl_radius < dac) .OR. &
483 : (MAXVAL(set_radius_b(:)) + ppl_radius < dbc)) THEN
484 : CYCLE
485 : END IF
486 :
487 : DO iset = 1, nseta
488 : IF (set_radius_a(iset) + ppl_radius < dac) CYCLE
489 : ncoa = npgfa(iset)*ncoset(la_max(iset))
490 : sgfa = first_sgfa(1, iset)
491 : DO jset = 1, nsetb
492 : IF (set_radius_b(jset) + ppl_radius < dbc) CYCLE
493 : ncob = npgfb(jset)*ncoset(lb_max(jset))
494 : sgfb = first_sgfb(1, jset)
495 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
496 : ! *** Calculate the GTH pseudo potential forces ***
497 : IF (doat) THEN
498 : atk0 = f0*SUM(hab(1:ncoa, 1:ncob, iset, jset)* &
499 : pab(1:ncoa, 1:ncob, iset, jset))
500 : END IF
501 : IF (calculate_forces) THEN
502 :
503 : force_a(:) = 0.0_dp
504 : force_b(:) = 0.0_dp
505 :
506 : IF (do_upf) THEN
507 : CALL upf_local_matrix(sgp_potential%upf_local, &
508 : la_max(iset), zeta(:npgfa(iset), iset), &
509 : lb_max(jset), zetb(:npgfb(jset), jset), rab, rac, &
510 : upf_v(:ncoa, :ncob), upf_da(:ncoa, :ncob, :), upf_db(:ncoa, :ncob, :))
511 : hab(:ncoa, :ncob, iset, jset) = hab(:ncoa, :ncob, iset, jset) + upf_v(:ncoa, :ncob)
512 : DO i = 1, 3
513 : force_a(i) = SUM(pab(:ncoa, :ncob, iset, jset)*upf_da(:ncoa, :ncob, i))
514 : force_b(i) = SUM(pab(:ncoa, :ncob, iset, jset)*upf_db(:ncoa, :ncob, i))
515 : END DO
516 : ELSE IF (only_gaussians) THEN
517 : CALL ppl_integral( &
518 : la_max(iset), la_min(iset), npgfa(iset), &
519 : rpgfa(:, iset), zeta(:, iset), &
520 : lb_max(jset), lb_min(jset), npgfb(jset), &
521 : rpgfb(:, jset), zetb(:, jset), &
522 : nexp_ppl, alpha_ppl, nct_ppl, cval_ppl, ppl_radius, &
523 : rab, dab, rac, dac, rbc, dbc, &
524 : hab(:, :, iset, jset), ppl_work, pab(:, :, iset, jset), &
525 : force_a, force_b, ppl_fwork)
526 : ELSE IF (libgrpp_local) THEN
527 : !$OMP CRITICAL(type1)
528 : CALL libgrpp_local_forces_ref(la_max(iset), la_min(iset), npgfa(iset), &
529 : rpgfa(:, iset), zeta(:, iset), &
530 : lb_max(jset), lb_min(jset), npgfb(jset), &
531 : rpgfb(:, jset), zetb(:, jset), &
532 : nexp_ppl, alpha_ppl, cval_ppl(1, :), nct_ppl, &
533 : ppl_radius, rab, dab, rac, dac, dbc, &
534 : hab(:, :, iset, jset), pab(:, :, iset, jset), &
535 : force_a, force_b)
536 : !$OMP END CRITICAL(type1)
537 : ELSE
538 : CALL ecploc_integral( &
539 : la_max(iset), la_min(iset), npgfa(iset), &
540 : rpgfa(:, iset), zeta(:, iset), &
541 : lb_max(jset), lb_min(jset), npgfb(jset), &
542 : rpgfb(:, jset), zetb(:, jset), &
543 : nexp_ppl, alpha_ppl, nct_ppl, cval_ppl, ppl_radius, &
544 : rab, dab, rac, dac, rbc, dbc, &
545 : hab(:, :, iset, jset), ppl_work, pab(:, :, iset, jset), &
546 : force_a, force_b, ppl_fwork)
547 : END IF
548 :
549 : IF (ecp_semi_local) THEN
550 :
551 : !$OMP CRITICAL(type2)
552 : CALL libgrpp_semilocal_forces_ref(la_max(iset), la_min(iset), npgfa(iset), &
553 : rpgfa(:, iset), zeta(:, iset), &
554 : lb_max(jset), lb_min(jset), npgfb(jset), &
555 : rpgfb(:, jset), zetb(:, jset), &
556 : slmax, npot, bpot, apot, nrpot, &
557 : ppl_radius, rab, dab, rac, dac, dbc, &
558 : hab(:, :, iset, jset), pab(:, :, iset, jset), &
559 : force_a, force_b)
560 : !$OMP END CRITICAL(type2)
561 : END IF
562 : ! *** The derivatives w.r.t. atomic center c are ***
563 : ! *** calculated using the translational invariance ***
564 : ! *** of the first derivatives ***
565 :
566 : force_thread(1, iatom) = force_thread(1, iatom) + f0*force_a(1)
567 : force_thread(2, iatom) = force_thread(2, iatom) + f0*force_a(2)
568 : force_thread(3, iatom) = force_thread(3, iatom) + f0*force_a(3)
569 : force_thread(1, katom) = force_thread(1, katom) - f0*force_a(1)
570 : force_thread(2, katom) = force_thread(2, katom) - f0*force_a(2)
571 : force_thread(3, katom) = force_thread(3, katom) - f0*force_a(3)
572 :
573 : force_thread(1, jatom) = force_thread(1, jatom) + f0*force_b(1)
574 : force_thread(2, jatom) = force_thread(2, jatom) + f0*force_b(2)
575 : force_thread(3, jatom) = force_thread(3, jatom) + f0*force_b(3)
576 : force_thread(1, katom) = force_thread(1, katom) - f0*force_b(1)
577 : force_thread(2, katom) = force_thread(2, katom) - f0*force_b(2)
578 : force_thread(3, katom) = force_thread(3, katom) - f0*force_b(3)
579 :
580 : IF (use_virial) THEN
581 : CALL virial_pair_force(pv_thread, f0, force_a, rac)
582 : CALL virial_pair_force(pv_thread, f0, force_b, rbc)
583 : END IF
584 : ELSE IF (do_dR) THEN
585 : IF (do_upf) THEN
586 : CALL upf_local_matrix(sgp_potential%upf_local, &
587 : la_max(iset), zeta(:npgfa(iset), iset), &
588 : lb_max(jset), zetb(:npgfb(jset), jset), rab, rac, &
589 : upf_v(:ncoa, :ncob), upf_da(:ncoa, :ncob, :), upf_db(:ncoa, :ncob, :))
590 : hab(:ncoa, :ncob, iset, jset) = hab(:ncoa, :ncob, iset, jset) + upf_v(:ncoa, :ncob)
591 : DO i = 1, 3
592 : hab2(:ncoa, :ncob, i, iset, jset) = hab2(:ncoa, :ncob, i, iset, jset) &
593 : + upf_da(:ncoa, :ncob, i)*(deltaR(i, iatom) - deltaR(i, katom)) &
594 : + upf_db(:ncoa, :ncob, i)*(deltaR(i, jatom) - deltaR(i, katom))
595 : END DO
596 : ELSE
597 : hab2_w = 0._dp
598 : CALL ppl_integral( &
599 : la_max(iset), la_min(iset), npgfa(iset), &
600 : rpgfa(:, iset), zeta(:, iset), &
601 : lb_max(jset), lb_min(jset), npgfb(jset), &
602 : rpgfb(:, jset), zetb(:, jset), &
603 : nexp_ppl, alpha_ppl, nct_ppl, cval_ppl, ppl_radius, &
604 : rab, dab, rac, dac, rbc, dbc, &
605 : vab=hab(:, :, iset, jset), s=ppl_work, &
606 : hab2=hab2(:, :, :, iset, jset), hab2_work=hab2_w, fs=ppl_fwork, &
607 : deltaR=deltaR, iatom=iatom, jatom=jatom, katom=katom)
608 : END IF
609 : IF (ecp_semi_local) THEN
610 : ! semi local ECP part
611 : CPABORT("Option not implemented")
612 : END IF
613 : ELSE
614 : IF (do_upf) THEN
615 : CALL upf_local_matrix(sgp_potential%upf_local, &
616 : la_max(iset), zeta(:npgfa(iset), iset), &
617 : lb_max(jset), zetb(:npgfb(jset), jset), rab, rac, &
618 : upf_v(:ncoa, :ncob))
619 : hab(:ncoa, :ncob, iset, jset) = hab(:ncoa, :ncob, iset, jset) + upf_v(:ncoa, :ncob)
620 : ELSE IF (only_gaussians) THEN
621 : !If the local part of the pseudo-potential only has Gaussian functions
622 : !we can use CP2K native code, that can run without libgrpp installation
623 : CALL ppl_integral( &
624 : la_max(iset), la_min(iset), npgfa(iset), &
625 : rpgfa(:, iset), zeta(:, iset), &
626 : lb_max(jset), lb_min(jset), npgfb(jset), &
627 : rpgfb(:, jset), zetb(:, jset), &
628 : nexp_ppl, alpha_ppl, nct_ppl, cval_ppl, ppl_radius, &
629 : rab, dab, rac, dac, rbc, dbc, hab(:, :, iset, jset), ppl_work)
630 :
631 : ELSE IF (libgrpp_local) THEN
632 : !If the local part of the potential is more complex, we need libgrpp
633 : !$OMP CRITICAL(type1)
634 : CALL libgrpp_local_integrals(la_max(iset), la_min(iset), npgfa(iset), &
635 : rpgfa(:, iset), zeta(:, iset), &
636 : lb_max(jset), lb_min(jset), npgfb(jset), &
637 : rpgfb(:, jset), zetb(:, jset), &
638 : nexp_ppl, alpha_ppl, cval_ppl(1, :), nct_ppl, &
639 : ppl_radius, rab, dab, rac, dac, dbc, &
640 : hab(:, :, iset, jset))
641 : !$OMP END CRITICAL(type1)
642 : ELSE
643 : CALL ecploc_integral( &
644 : la_max(iset), la_min(iset), npgfa(iset), &
645 : rpgfa(:, iset), zeta(:, iset), &
646 : lb_max(jset), lb_min(jset), npgfb(jset), &
647 : rpgfb(:, jset), zetb(:, jset), &
648 : nexp_ppl, alpha_ppl, nct_ppl, cval_ppl, ppl_radius, &
649 : rab, dab, rac, dac, rbc, dbc, hab(:, :, iset, jset), ppl_work)
650 : END IF
651 :
652 : IF (ecp_semi_local) THEN
653 : ! semi local ECP part
654 : !$OMP CRITICAL(type2)
655 : CALL libgrpp_semilocal_integrals(la_max(iset), la_min(iset), npgfa(iset), &
656 : rpgfa(:, iset), zeta(:, iset), &
657 : lb_max(jset), lb_min(jset), npgfb(jset), &
658 : rpgfb(:, jset), zetb(:, jset), &
659 : slmax, npot, bpot, apot, nrpot, &
660 : ppl_radius, rab, dab, rac, dac, dbc, &
661 : hab(:, :, iset, jset))
662 : !$OMP END CRITICAL(type2)
663 : END IF
664 : END IF
665 : ! calculate atomic contributions
666 : IF (doat) THEN
667 : atk1 = f0*SUM(hab(1:ncoa, 1:ncob, iset, jset)* &
668 : pab(1:ncoa, 1:ncob, iset, jset))
669 : at_thread(katom) = at_thread(katom) + (atk1 - atk0)
670 : END IF
671 : END DO
672 : END DO
673 : END DO
674 : END DO
675 :
676 : ! *** Contract PPL integrals
677 : IF (.NOT. do_dR) THEN
678 : DO iset = 1, nseta
679 : ncoa = npgfa(iset)*ncoset(la_max(iset))
680 : sgfa = first_sgfa(1, iset)
681 : DO jset = 1, nsetb
682 : ncob = npgfb(jset)*ncoset(lb_max(jset))
683 : sgfb = first_sgfb(1, jset)
684 :
685 : !$ hash2 = MOD((iset - 1)*nsetb + jset, nlock) + 1
686 : !$ hash = MOD(hash1 + hash2, nlock) + 1
687 :
688 : work(1:ncoa, 1:nsgfb(jset)) = MATMUL(hab(1:ncoa, 1:ncob, iset, jset), &
689 : sphi_b(1:ncob, sgfb:sgfb + nsgfb(jset) - 1))
690 : !$ CALL omp_set_lock(locks(hash))
691 : IF (iatom <= jatom) THEN
692 : h_block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) = &
693 : h_block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) + &
694 : MATMUL(TRANSPOSE(sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1)), work(1:ncoa, 1:nsgfb(jset)))
695 : ELSE
696 : h_block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) = &
697 : h_block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) + &
698 : MATMUL(TRANSPOSE(work(1:ncoa, 1:nsgfb(jset))), sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1))
699 : END IF
700 : !$ CALL omp_unset_lock(locks(hash))
701 :
702 : END DO
703 : END DO
704 : ELSE ! do_dr == .true.
705 : DO iset = 1, nseta
706 : ncoa = npgfa(iset)*ncoset(la_max(iset))
707 : sgfa = first_sgfa(1, iset)
708 : DO jset = 1, nsetb
709 : ncob = npgfb(jset)*ncoset(lb_max(jset))
710 : sgfb = first_sgfb(1, jset)
711 : work(1:ncoa, 1:nsgfb(jset)) = MATMUL(hab2(1:ncoa, 1:ncob, 1, iset, jset), &
712 : sphi_b(1:ncob, sgfb:sgfb + nsgfb(jset) - 1))
713 :
714 : !$OMP CRITICAL(h1_1block_critical)
715 : IF (iatom <= jatom) THEN
716 : h1_1block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) = &
717 : h1_1block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) + &
718 : MATMUL(TRANSPOSE(sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1)), work(1:ncoa, 1:nsgfb(jset)))
719 :
720 : ELSE
721 : h1_1block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) = &
722 : h1_1block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) + &
723 : MATMUL(TRANSPOSE(work(1:ncoa, 1:nsgfb(jset))), sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1))
724 : END IF
725 : !$OMP END CRITICAL(h1_1block_critical)
726 : work(1:ncoa, 1:nsgfb(jset)) = MATMUL(hab2(1:ncoa, 1:ncob, 2, iset, jset), &
727 : sphi_b(1:ncob, sgfb:sgfb + nsgfb(jset) - 1))
728 :
729 : !$OMP CRITICAL(h1_2block_critical)
730 : IF (iatom <= jatom) THEN
731 : h1_2block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) = &
732 : h1_2block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) + &
733 : MATMUL(TRANSPOSE(sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1)), work(1:ncoa, 1:nsgfb(jset)))
734 :
735 : ELSE
736 : h1_2block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) = &
737 : h1_2block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) + &
738 : MATMUL(TRANSPOSE(work(1:ncoa, 1:nsgfb(jset))), sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1))
739 : END IF
740 : !$OMP END CRITICAL(h1_2block_critical)
741 : work(1:ncoa, 1:nsgfb(jset)) = MATMUL(hab2(1:ncoa, 1:ncob, 3, iset, jset), &
742 : sphi_b(1:ncob, sgfb:sgfb + nsgfb(jset) - 1))
743 : !$OMP CRITICAL(h1_3block_critical)
744 : IF (iatom <= jatom) THEN
745 : h1_3block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) = &
746 : h1_3block(sgfa:sgfa + nsgfa(iset) - 1, sgfb:sgfb + nsgfb(jset) - 1) + &
747 : MATMUL(TRANSPOSE(sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1)), work(1:ncoa, 1:nsgfb(jset)))
748 :
749 : ELSE
750 : h1_3block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) = &
751 : h1_3block(sgfb:sgfb + nsgfb(jset) - 1, sgfa:sgfa + nsgfa(iset) - 1) + &
752 : MATMUL(TRANSPOSE(work(1:ncoa, 1:nsgfb(jset))), sphi_a(1:ncoa, sgfa:sgfa + nsgfa(iset) - 1))
753 : END IF
754 : !$OMP END CRITICAL(h1_3block_critical)
755 : END DO
756 : END DO
757 : END IF
758 : IF (do_dR) DEALLOCATE (hab2, ppl_fwork, hab2_w)
759 : END DO ! slot
760 :
761 : DEALLOCATE (hab, work, ppl_work)
762 : IF (ALLOCATED(upf_v)) DEALLOCATE (upf_v)
763 : IF (ALLOCATED(upf_da)) DEALLOCATE (upf_da, upf_db)
764 : IF (calculate_forces .OR. doat) THEN
765 : DEALLOCATE (pab, ppl_fwork)
766 : END IF
767 :
768 : !$OMP DO
769 : !$ DO lock_num = 1, nlock
770 : !$ call omp_destroy_lock(locks(lock_num))
771 : !$ END DO
772 : !$OMP END DO
773 :
774 : !$OMP SINGLE
775 : !$ DEALLOCATE (locks)
776 : !$OMP END SINGLE NOWAIT
777 :
778 : !$OMP END PARALLEL
779 :
780 21070 : CALL neighbor_list_iterator_release(ap_iterator)
781 :
782 21070 : DEALLOCATE (basis_set_list)
783 :
784 21070 : IF (calculate_forces .OR. doat) THEN
785 : ! *** If LSD, then recover alpha density and beta density ***
786 : ! *** from the total density (1) and the spin density (2) ***
787 8039 : IF (SIZE(matrix_p, 1) == 2) THEN
788 3734 : DO img = 1, nimages
789 : CALL dbcsr_add(matrix_p(1, img)%matrix, matrix_p(2, img)%matrix, &
790 2750 : alpha_scalar=0.5_dp, beta_scalar=0.5_dp)
791 : CALL dbcsr_add(matrix_p(2, img)%matrix, matrix_p(1, img)%matrix, &
792 3734 : alpha_scalar=-1.0_dp, beta_scalar=1.0_dp)
793 : END DO
794 : END IF
795 : END IF
796 :
797 21070 : IF (calculate_forces) THEN
798 7977 : CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, kind_of=kind_of)
799 : !$OMP DO
800 : DO iatom = 1, natom
801 28335 : atom_a = atom_of_kind(iatom)
802 28335 : ikind = kind_of(iatom)
803 113340 : force(ikind)%gth_ppl(:, atom_a) = force(ikind)%gth_ppl(:, atom_a) + force_thread(:, iatom)
804 : END DO
805 : !$OMP END DO
806 7977 : DEALLOCATE (atom_of_kind, kind_of)
807 : END IF
808 21070 : IF (doat) THEN
809 280 : atcore(1:natom) = atcore(1:natom) + at_thread(1:natom)
810 : END IF
811 :
812 21070 : IF (calculate_forces .AND. use_virial) THEN
813 12558 : virial%pv_ppl = virial%pv_ppl + pv_thread
814 12558 : virial%pv_virial = virial%pv_virial + pv_thread
815 : END IF
816 :
817 21070 : CALL timestop(handle)
818 :
819 63210 : END SUBROUTINE build_core_ppl
820 :
821 : ! **************************************************************************************************
822 : !> \brief ...
823 : !> \param lri_ppl_coef ...
824 : !> \param force ...
825 : !> \param virial ...
826 : !> \param calculate_forces ...
827 : !> \param use_virial ...
828 : !> \param qs_kind_set ...
829 : !> \param atomic_kind_set ...
830 : !> \param particle_set ...
831 : !> \param sac_ppl ...
832 : !> \param basis_type ...
833 : ! **************************************************************************************************
834 4 : SUBROUTINE build_core_ppl_ri(lri_ppl_coef, force, virial, calculate_forces, use_virial, &
835 : qs_kind_set, atomic_kind_set, particle_set, sac_ppl, &
836 : basis_type)
837 :
838 : TYPE(lri_kind_type), DIMENSION(:), POINTER :: lri_ppl_coef
839 : TYPE(qs_force_type), DIMENSION(:), POINTER :: force
840 : TYPE(virial_type), POINTER :: virial
841 : LOGICAL, INTENT(IN) :: calculate_forces
842 : LOGICAL :: use_virial
843 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
844 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
845 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
846 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
847 : POINTER :: sac_ppl
848 : CHARACTER(LEN=*), INTENT(IN) :: basis_type
849 :
850 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_core_ppl_ri'
851 : INTEGER, PARAMETER :: nexp_max = 30
852 :
853 : INTEGER :: atom_a, handle, i, iatom, ikind, iset, katom, kkind, maxco, maxlgto, maxsgf, &
854 : n_local, natom, ncoa, nexp_lpot, nexp_ppl, nfun, nkind, nloc, nseta, sgfa, sgfb, slot
855 4 : INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, kind_of
856 : INTEGER, DIMENSION(1:10) :: nrloc
857 4 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, nct_lpot, npgfa, nsgfa
858 4 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa
859 : INTEGER, DIMENSION(nexp_max) :: nct_ppl
860 : LOGICAL :: do_upf, ecp_local, ecp_semi_local, &
861 : lpotextended
862 : REAL(KIND=dp) :: alpha, dac, ppl_radius
863 4 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: va, work
864 4 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: dva, dvas
865 : REAL(KIND=dp), DIMENSION(1:10) :: aloc, bloc
866 : REAL(KIND=dp), DIMENSION(3) :: force_a, rac
867 : REAL(KIND=dp), DIMENSION(3, 3) :: pv_thread
868 : TYPE(gto_basis_set_type), POINTER :: basis_set
869 4 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
870 : TYPE(gth_potential_type), POINTER :: gth_potential
871 : REAL(KIND=dp), DIMENSION(nexp_max) :: alpha_ppl
872 4 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: bcon, cval_lpot, rpgfa, sphi_a, zeta
873 4 : REAL(KIND=dp), DIMENSION(:), POINTER :: a_local, alpha_lpot, c_local, cexp_ppl, &
874 4 : set_radius_a
875 : REAL(KIND=dp), DIMENSION(4, nexp_max) :: cval_ppl
876 8 : REAL(KIND=dp), DIMENSION(3, SIZE(particle_set)) :: force_thread
877 : TYPE(sgp_potential_type), POINTER :: sgp_potential
878 :
879 : !$ INTEGER(kind=omp_lock_kind), &
880 4 : !$ ALLOCATABLE, DIMENSION(:) :: locks
881 : !$ INTEGER :: lock_num, hash
882 : !$ INTEGER, PARAMETER :: nlock = 501
883 :
884 8 : IF (calculate_forces) THEN
885 2 : CALL timeset(routineN//"_forces", handle)
886 : ELSE
887 2 : CALL timeset(routineN, handle)
888 : END IF
889 :
890 4 : nkind = SIZE(atomic_kind_set)
891 4 : natom = SIZE(particle_set)
892 :
893 52 : force_thread = 0.0_dp
894 4 : pv_thread = 0.0_dp
895 4 : CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, kind_of=kind_of)
896 :
897 20 : ALLOCATE (basis_set_list(nkind))
898 12 : DO ikind = 1, nkind
899 8 : CALL get_qs_kind(qs_kind_set(ikind), basis_set=basis_set, basis_type=basis_type)
900 12 : IF (ASSOCIATED(basis_set)) THEN
901 8 : basis_set_list(ikind)%gto_basis_set => basis_set
902 : ELSE
903 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
904 : END IF
905 : END DO
906 :
907 4 : CALL get_qs_kind_set(qs_kind_set, maxco=maxco, maxsgf=maxsgf, maxlgto=maxlgto, basis_type=basis_type)
908 4 : CALL prepare_upf_local(qs_kind_set, maxlgto + 1)
909 :
910 : !$OMP PARALLEL &
911 : !$OMP DEFAULT (NONE) &
912 : !$OMP SHARED (maxco,maxsgf,basis_set_list,calculate_forces,lri_ppl_coef,qs_kind_set,&
913 : !$OMP locks,natom,use_virial,virial,ncoset,atom_of_kind,sac_ppl) &
914 : !$OMP PRIVATE (ikind,kkind,iatom,katom,atom_a,rac,va,dva,dvas,basis_set,slot,&
915 : !$OMP first_sgfa,la_max,la_min,npgfa,nseta,nsgfa,rpgfa,set_radius_a,lock_num,&
916 : !$OMP sphi_a,zeta,gth_potential,sgp_potential,alpha,cexp_ppl,lpotextended,ppl_radius,&
917 : !$OMP nexp_ppl,alpha_ppl,nct_ppl,cval_ppl,nloc,n_local,nrloc,a_local,aloc,bloc,c_local,nfun,work,&
918 : !$OMP hash,dac,force_a,iset,sgfa,sgfb,ncoa,bcon,cval_lpot,nct_lpot,alpha_lpot,nexp_lpot,&
919 : !$OMP ecp_local,ecp_semi_local,do_upf) &
920 4 : !$OMP REDUCTION (+ : pv_thread, force_thread )
921 :
922 : !$OMP SINGLE
923 : !$ ALLOCATE (locks(nlock))
924 : !$OMP END SINGLE
925 :
926 : !$OMP DO
927 : !$ DO lock_num = 1, nlock
928 : !$ call omp_init_lock(locks(lock_num))
929 : !$ END DO
930 : !$OMP END DO
931 :
932 : ALLOCATE (va(maxco), work(maxsgf))
933 : IF (calculate_forces) THEN
934 : ALLOCATE (dva(maxco, 3), dvas(maxco, 3))
935 : END IF
936 :
937 : !$OMP DO SCHEDULE(GUIDED)
938 : DO slot = 1, sac_ppl(1)%nl_size
939 :
940 : ikind = sac_ppl(1)%nlist_task(slot)%ikind
941 : kkind = sac_ppl(1)%nlist_task(slot)%jkind
942 : iatom = sac_ppl(1)%nlist_task(slot)%iatom
943 : katom = sac_ppl(1)%nlist_task(slot)%jatom
944 : rac(1:3) = sac_ppl(1)%nlist_task(slot)%r(1:3)
945 : atom_a = atom_of_kind(iatom)
946 :
947 : basis_set => basis_set_list(ikind)%gto_basis_set
948 : IF (.NOT. ASSOCIATED(basis_set)) CYCLE
949 :
950 : ! basis ikind
951 : first_sgfa => basis_set%first_sgf
952 : la_max => basis_set%lmax
953 : la_min => basis_set%lmin
954 : npgfa => basis_set%npgf
955 : nseta = basis_set%nset
956 : nsgfa => basis_set%nsgf_set
957 : nfun = basis_set%nsgf
958 : rpgfa => basis_set%pgf_radius
959 : set_radius_a => basis_set%set_radius
960 : sphi_a => basis_set%sphi
961 : zeta => basis_set%zet
962 :
963 : CALL get_qs_kind(qs_kind_set(kkind), gth_potential=gth_potential, &
964 : sgp_potential=sgp_potential)
965 : ecp_semi_local = .FALSE.
966 : do_upf = .FALSE.
967 : IF (ASSOCIATED(gth_potential)) THEN
968 : CALL get_potential(potential=gth_potential, &
969 : alpha_ppl=alpha, cexp_ppl=cexp_ppl, &
970 : lpot_present=lpotextended, ppl_radius=ppl_radius)
971 : nexp_ppl = 1
972 : alpha_ppl(1) = alpha
973 : nct_ppl(1) = SIZE(cexp_ppl)
974 : cval_ppl(1:nct_ppl(1), 1) = cexp_ppl(1:nct_ppl(1))
975 : IF (lpotextended) THEN
976 : CALL get_potential(potential=gth_potential, &
977 : nexp_lpot=nexp_lpot, alpha_lpot=alpha_lpot, nct_lpot=nct_lpot, cval_lpot=cval_lpot)
978 : CPASSERT(nexp_lpot < nexp_max)
979 : nexp_ppl = nexp_lpot + 1
980 : alpha_ppl(2:nexp_lpot + 1) = alpha_lpot(1:nexp_lpot)
981 : nct_ppl(2:nexp_lpot + 1) = nct_lpot(1:nexp_lpot)
982 : DO i = 1, nexp_lpot
983 : cval_ppl(1:nct_lpot(i), i + 1) = cval_lpot(1:nct_lpot(i), i)
984 : END DO
985 : END IF
986 : ELSE IF (ASSOCIATED(sgp_potential)) THEN
987 : CALL get_potential(potential=sgp_potential, ecp_local=ecp_local, ecp_semi_local=ecp_semi_local, &
988 : ppl_radius=ppl_radius)
989 : CPASSERT(.NOT. ecp_semi_local)
990 : do_upf = ALLOCATED(sgp_potential%upf_data)
991 : IF (do_upf) THEN
992 : CPASSERT(.NOT. ecp_local)
993 : ELSE IF (ecp_local) THEN
994 : CALL get_potential(potential=sgp_potential, nloc=nloc, nrloc=nrloc, aloc=aloc, bloc=bloc)
995 : IF (SUM(ABS(aloc(1:nloc))) < 1.0e-12_dp) CYCLE
996 : nexp_ppl = nloc
997 : CPASSERT(nexp_ppl <= nexp_max)
998 : nct_ppl(1:nloc) = nrloc(1:nloc)
999 : alpha_ppl(1:nloc) = bloc(1:nloc)
1000 : cval_ppl(1, 1:nloc) = aloc(1:nloc)
1001 : ELSE
1002 : CALL get_potential(potential=sgp_potential, n_local=n_local, a_local=a_local, c_local=c_local)
1003 : nexp_ppl = n_local
1004 : CPASSERT(nexp_ppl <= nexp_max)
1005 : nct_ppl(1:n_local) = 1
1006 : alpha_ppl(1:n_local) = a_local(1:n_local)
1007 : cval_ppl(1, 1:n_local) = c_local(1:n_local)
1008 : END IF
1009 : ELSE
1010 : CYCLE
1011 : END IF
1012 :
1013 : dac = SQRT(SUM(rac*rac))
1014 : IF ((MAXVAL(set_radius_a(:)) + ppl_radius < dac)) CYCLE
1015 : IF (calculate_forces) force_a = 0.0_dp
1016 : work(1:nfun) = 0.0_dp
1017 :
1018 : DO iset = 1, nseta
1019 : IF (set_radius_a(iset) + ppl_radius < dac) CYCLE
1020 : ! integrals
1021 : ncoa = npgfa(iset)*ncoset(la_max(iset))
1022 : IF (do_upf) THEN
1023 : IF (calculate_forces) THEN
1024 : CALL upf_local_ri(sgp_potential%upf_local, la_max(iset), zeta(:npgfa(iset), iset), &
1025 : rac, va(:ncoa), dva(:ncoa, :))
1026 : ELSE
1027 : CALL upf_local_ri(sgp_potential%upf_local, la_max(iset), zeta(:npgfa(iset), iset), rac, va(:ncoa))
1028 : END IF
1029 : ELSE IF (calculate_forces) THEN
1030 : va = 0.0_dp
1031 : dva = 0.0_dp
1032 : CALL ppl_integral_ri( &
1033 : la_max(iset), la_min(iset), npgfa(iset), rpgfa(:, iset), zeta(:, iset), &
1034 : nexp_ppl, alpha_ppl, nct_ppl, cval_ppl, ppl_radius, &
1035 : -rac, dac, va, dva)
1036 : ELSE
1037 : va = 0.0_dp
1038 : CALL ppl_integral_ri( &
1039 : la_max(iset), la_min(iset), npgfa(iset), rpgfa(:, iset), zeta(:, iset), &
1040 : nexp_ppl, alpha_ppl, nct_ppl, cval_ppl, ppl_radius, &
1041 : -rac, dac, va)
1042 : END IF
1043 : ! contraction
1044 : sgfa = first_sgfa(1, iset)
1045 : sgfb = sgfa + nsgfa(iset) - 1
1046 : ncoa = npgfa(iset)*ncoset(la_max(iset))
1047 : bcon => sphi_a(1:ncoa, sgfa:sgfb)
1048 : work(sgfa:sgfb) = MATMUL(TRANSPOSE(bcon), va(1:ncoa))
1049 : IF (calculate_forces) THEN
1050 : dvas(1:nsgfa(iset), 1:3) = MATMUL(TRANSPOSE(bcon), dva(1:ncoa, 1:3))
1051 : force_a(1) = force_a(1) + SUM(lri_ppl_coef(ikind)%acoef(atom_a, sgfa:sgfb)*dvas(1:nsgfa(iset), 1))
1052 : force_a(2) = force_a(2) + SUM(lri_ppl_coef(ikind)%acoef(atom_a, sgfa:sgfb)*dvas(1:nsgfa(iset), 2))
1053 : force_a(3) = force_a(3) + SUM(lri_ppl_coef(ikind)%acoef(atom_a, sgfa:sgfb)*dvas(1:nsgfa(iset), 3))
1054 : END IF
1055 : END DO
1056 : !$ hash = MOD(iatom, nlock) + 1
1057 : !$ CALL omp_set_lock(locks(hash))
1058 : lri_ppl_coef(ikind)%v_int(atom_a, 1:nfun) = lri_ppl_coef(ikind)%v_int(atom_a, 1:nfun) + work(1:nfun)
1059 : !$ CALL omp_unset_lock(locks(hash))
1060 : IF (calculate_forces) THEN
1061 : force_thread(1, iatom) = force_thread(1, iatom) + force_a(1)
1062 : force_thread(2, iatom) = force_thread(2, iatom) + force_a(2)
1063 : force_thread(3, iatom) = force_thread(3, iatom) + force_a(3)
1064 : force_thread(1, katom) = force_thread(1, katom) - force_a(1)
1065 : force_thread(2, katom) = force_thread(2, katom) - force_a(2)
1066 : force_thread(3, katom) = force_thread(3, katom) - force_a(3)
1067 : IF (use_virial) THEN
1068 : CALL virial_pair_force(pv_thread, 1.0_dp, force_a, rac)
1069 : END IF
1070 : END IF
1071 : END DO
1072 :
1073 : DEALLOCATE (va, work)
1074 : IF (calculate_forces) THEN
1075 : DEALLOCATE (dva, dvas)
1076 : END IF
1077 :
1078 : !$OMP END PARALLEL
1079 :
1080 4 : IF (calculate_forces) THEN
1081 8 : DO iatom = 1, natom
1082 6 : atom_a = atom_of_kind(iatom)
1083 6 : ikind = kind_of(iatom)
1084 6 : force(ikind)%gth_ppl(1, atom_a) = force(ikind)%gth_ppl(1, atom_a) + force_thread(1, iatom)
1085 6 : force(ikind)%gth_ppl(2, atom_a) = force(ikind)%gth_ppl(2, atom_a) + force_thread(2, iatom)
1086 8 : force(ikind)%gth_ppl(3, atom_a) = force(ikind)%gth_ppl(3, atom_a) + force_thread(3, iatom)
1087 : END DO
1088 : END IF
1089 4 : DEALLOCATE (atom_of_kind, kind_of)
1090 :
1091 4 : IF (calculate_forces .AND. use_virial) THEN
1092 0 : virial%pv_ppl = virial%pv_ppl + pv_thread
1093 0 : virial%pv_virial = virial%pv_virial + pv_thread
1094 : END IF
1095 :
1096 4 : DEALLOCATE (basis_set_list)
1097 :
1098 4 : CALL timestop(handle)
1099 :
1100 12 : END SUBROUTINE build_core_ppl_ri
1101 :
1102 : ! **************************************************************************************************
1103 :
1104 : ! **************************************************************************************************
1105 : !> \brief Initialize immutable native local-potential caches before OpenMP work.
1106 : !> \param qs_kind_set Atomic kinds with original UPF data.
1107 : !> \param degree Maximum Cartesian product degree required by the caller.
1108 : !> \param have_upf Whether any kind uses the native local operator.
1109 : ! **************************************************************************************************
1110 21074 : SUBROUTINE prepare_upf_local(qs_kind_set, degree, have_upf)
1111 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1112 : INTEGER, INTENT(IN) :: degree
1113 : LOGICAL, INTENT(OUT), OPTIONAL :: have_upf
1114 :
1115 : INTEGER :: ikind
1116 : TYPE(sgp_potential_type), POINTER :: potential
1117 :
1118 21074 : IF (PRESENT(have_upf)) have_upf = .FALSE.
1119 57883 : DO ikind = 1, SIZE(qs_kind_set)
1120 36809 : CALL get_qs_kind(qs_kind_set(ikind), sgp_potential=potential)
1121 36809 : IF (.NOT. ASSOCIATED(potential)) CYCLE
1122 234 : IF (.NOT. ALLOCATED(potential%upf_data)) CYCLE
1123 36 : IF (PRESENT(have_upf)) have_upf = .TRUE.
1124 21110 : IF (potential%upf_local%radial%degree < degree) THEN
1125 24 : CALL upf_local_init(potential%upf_data, potential%alpha_core_charge, degree, potential%upf_local)
1126 : END IF
1127 : END DO
1128 21074 : END SUBROUTINE prepare_upf_local
1129 :
1130 : END MODULE core_ppl
|