Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \par History
10 : !> created 07.2005
11 : !> \author MI (07.2005)
12 : ! **************************************************************************************************
13 : MODULE qs_operators_ao
14 : USE ai_moments, ONLY: diff_momop,&
15 : diffop,&
16 : moment
17 : USE ai_os_rr, ONLY: os_rr_ovlp
18 : USE basis_set_types, ONLY: gto_basis_set_p_type,&
19 : gto_basis_set_type
20 : USE block_p_types, ONLY: block_p_type
21 : USE cell_types, ONLY: cell_type,&
22 : pbc
23 : USE cp_dbcsr_api, ONLY: dbcsr_get_block_p,&
24 : dbcsr_get_matrix_type,&
25 : dbcsr_has_symmetry,&
26 : dbcsr_p_type,&
27 : dbcsr_type_antisymmetric,&
28 : dbcsr_type_no_symmetry
29 : USE cp_log_handling, ONLY: cp_get_default_logger,&
30 : cp_logger_type
31 : USE kinds, ONLY: default_string_length,&
32 : dp
33 : USE mathconstants, ONLY: pi
34 : USE message_passing, ONLY: mp_para_env_type
35 : USE orbital_pointers, ONLY: coset,&
36 : init_orbital_pointers,&
37 : ncoset
38 : USE particle_types, ONLY: particle_type
39 : USE qs_environment_types, ONLY: get_qs_env,&
40 : qs_environment_type
41 : USE qs_kind_types, ONLY: get_qs_kind,&
42 : get_qs_kind_set,&
43 : qs_kind_type
44 : USE qs_neighbor_list_types, ONLY: get_iterator_info,&
45 : neighbor_list_iterate,&
46 : neighbor_list_iterator_create,&
47 : neighbor_list_iterator_p_type,&
48 : neighbor_list_iterator_release,&
49 : neighbor_list_set_p_type
50 : #include "./base/base_uses.f90"
51 :
52 : IMPLICIT NONE
53 : PRIVATE
54 :
55 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_operators_ao'
56 :
57 : ! *** Public subroutines ***
58 :
59 : PUBLIC :: p_xyz_ao, rRc_xyz_ao, rRc_xyz_der_ao
60 : PUBLIC :: build_lin_mom_matrix, build_ang_mom_matrix
61 :
62 : CONTAINS
63 :
64 : ! **************************************************************************************************
65 : !> \brief Calculation of the linear momentum matrix <mu|∂|nu> over
66 : !> Cartesian Gaussian functions.
67 : !> \param qs_env ...
68 : !> \param matrix ...
69 : !> \date 27.02.2009
70 : !> \author VW
71 : !> \version 1.0
72 : ! **************************************************************************************************
73 1164 : SUBROUTINE build_lin_mom_matrix(qs_env, matrix)
74 :
75 : TYPE(qs_environment_type), POINTER :: qs_env
76 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix
77 :
78 : CHARACTER(len=*), PARAMETER :: routineN = 'build_lin_mom_matrix'
79 :
80 : INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
81 : ldai, maxco, maxlgto, maxsgf, natom, ncoa, ncob, neighbor_list_id, nkind, nseta, nsetb, &
82 : sgfa, sgfb
83 1164 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, npgfa, &
84 1164 : npgfb, nsgfa, nsgfb
85 1164 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
86 : LOGICAL :: do_symmetric, found, new_atom_b
87 : REAL(KIND=dp) :: dab, rab2
88 1164 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: work
89 1164 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: intab, rr_work
90 : REAL(KIND=dp), DIMENSION(3) :: rab
91 1164 : REAL(KIND=dp), DIMENSION(:), POINTER :: set_radius_a, set_radius_b
92 1164 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb
93 1164 : TYPE(block_p_type), ALLOCATABLE, DIMENSION(:) :: integral
94 : TYPE(cell_type), POINTER :: cell
95 : TYPE(cp_logger_type), POINTER :: logger
96 1164 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
97 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
98 : TYPE(mp_para_env_type), POINTER :: para_env
99 : TYPE(neighbor_list_iterator_p_type), &
100 1164 : DIMENSION(:), POINTER :: nl_iterator
101 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
102 1164 : POINTER :: sab_nl
103 1164 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
104 1164 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
105 : TYPE(qs_kind_type), POINTER :: qs_kind
106 :
107 1164 : CALL timeset(routineN, handle)
108 :
109 1164 : NULLIFY (cell, sab_nl, qs_kind_set, particle_set, para_env)
110 1164 : NULLIFY (logger)
111 :
112 1164 : logger => cp_get_default_logger()
113 :
114 : CALL get_qs_env(qs_env=qs_env, &
115 : qs_kind_set=qs_kind_set, &
116 : particle_set=particle_set, &
117 : neighbor_list_id=neighbor_list_id, &
118 : para_env=para_env, &
119 1164 : cell=cell)
120 :
121 1164 : nkind = SIZE(qs_kind_set)
122 1164 : natom = SIZE(particle_set)
123 :
124 : ! Take into account the symmetry of the input matrix
125 1164 : do_symmetric = dbcsr_has_symmetry(matrix(1)%matrix)
126 1164 : IF (do_symmetric) THEN
127 1162 : CALL get_qs_env(qs_env=qs_env, sab_orb=sab_nl)
128 : ELSE
129 2 : CALL get_qs_env(qs_env=qs_env, sab_all=sab_nl)
130 : END IF
131 : ! *** Allocate work storage ***
132 :
133 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
134 : maxco=maxco, &
135 : maxlgto=maxlgto, &
136 1164 : maxsgf=maxsgf)
137 :
138 1164 : ldai = ncoset(maxlgto + 1)
139 1164 : CALL init_orbital_pointers(ldai)
140 :
141 17460 : ALLOCATE (rr_work(ldai, ldai, 3), intab(maxco, maxco, 3), work(maxco, maxsgf), integral(3))
142 1164 : rr_work(:, :, :) = 0.0_dp
143 1164 : intab(:, :, :) = 0.0_dp
144 1164 : work(:, :) = 0.0_dp
145 :
146 5506 : ALLOCATE (basis_set_list(nkind))
147 3178 : DO ikind = 1, nkind
148 2014 : qs_kind => qs_kind_set(ikind)
149 2014 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
150 3178 : IF (ASSOCIATED(basis_set_a)) THEN
151 2014 : basis_set_list(ikind)%gto_basis_set => basis_set_a
152 : ELSE
153 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
154 : END IF
155 : END DO
156 1164 : CALL neighbor_list_iterator_create(nl_iterator, sab_nl)
157 65030 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
158 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
159 63866 : iatom=iatom, jatom=jatom, r=rab)
160 63866 : basis_set_a => basis_set_list(ikind)%gto_basis_set
161 63866 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
162 63866 : basis_set_b => basis_set_list(jkind)%gto_basis_set
163 63866 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
164 : ! basis ikind
165 63866 : first_sgfa => basis_set_a%first_sgf
166 63866 : la_max => basis_set_a%lmax
167 63866 : la_min => basis_set_a%lmin
168 63866 : npgfa => basis_set_a%npgf
169 63866 : nseta = basis_set_a%nset
170 63866 : nsgfa => basis_set_a%nsgf_set
171 63866 : rpgfa => basis_set_a%pgf_radius
172 63866 : set_radius_a => basis_set_a%set_radius
173 63866 : sphi_a => basis_set_a%sphi
174 63866 : zeta => basis_set_a%zet
175 : ! basis jkind
176 63866 : first_sgfb => basis_set_b%first_sgf
177 63866 : lb_max => basis_set_b%lmax
178 63866 : lb_min => basis_set_b%lmin
179 63866 : npgfb => basis_set_b%npgf
180 63866 : nsetb = basis_set_b%nset
181 63866 : nsgfb => basis_set_b%nsgf_set
182 63866 : rpgfb => basis_set_b%pgf_radius
183 63866 : set_radius_b => basis_set_b%set_radius
184 63866 : sphi_b => basis_set_b%sphi
185 63866 : zetb => basis_set_b%zet
186 :
187 63866 : IF (inode == 1) last_jatom = 0
188 63866 : IF (jatom /= last_jatom) THEN
189 : new_atom_b = .TRUE.
190 : last_jatom = jatom
191 : ELSE
192 : new_atom_b = .FALSE.
193 : END IF
194 :
195 : IF (new_atom_b) THEN
196 8764 : IF (do_symmetric) THEN
197 8755 : IF (iatom <= jatom) THEN
198 4976 : irow = iatom
199 4976 : icol = jatom
200 : ELSE
201 3779 : irow = jatom
202 3779 : icol = iatom
203 : END IF
204 : ELSE
205 9 : irow = iatom
206 9 : icol = jatom
207 : END IF
208 :
209 35056 : DO i = 1, 3
210 26292 : NULLIFY (integral(i)%block)
211 : CALL dbcsr_get_block_p(matrix=matrix(i)%matrix, &
212 26292 : row=irow, col=icol, BLOCK=integral(i)%block, found=found)
213 35056 : CPASSERT(ASSOCIATED(INTEGRAL(i)%block))
214 : END DO
215 : END IF
216 :
217 63866 : rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
218 63866 : dab = SQRT(rab2)
219 :
220 196717 : DO iset = 1, nseta
221 :
222 131687 : ncoa = npgfa(iset)*ncoset(la_max(iset))
223 131687 : sgfa = first_sgfa(1, iset)
224 :
225 489318 : DO jset = 1, nsetb
226 :
227 293765 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
228 :
229 125544 : ncob = npgfb(jset)*ncoset(lb_max(jset))
230 125544 : sgfb = first_sgfb(1, jset)
231 :
232 : ! *** Calculate the primitive fermi contact integrals ***
233 :
234 : CALL lin_mom(la_max(iset), la_min(iset), npgfa(iset), &
235 : rpgfa(:, iset), zeta(:, iset), &
236 : lb_max(jset), lb_min(jset), npgfb(jset), &
237 : rpgfb(:, jset), zetb(:, jset), &
238 125544 : rab, intab, SIZE(rr_work, 1), rr_work)
239 :
240 : ! *** Contraction step ***
241 :
242 633863 : DO i = 1, 3
243 :
244 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
245 : 1.0_dp, intab(1, 1, i), SIZE(intab, 1), &
246 : sphi_b(1, sgfb), SIZE(sphi_b, 1), &
247 376632 : 0.0_dp, work(1, 1), SIZE(work, 1))
248 :
249 670397 : IF (do_symmetric) THEN
250 376605 : IF (iatom <= jatom) THEN
251 :
252 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
253 : 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
254 : work(1, 1), SIZE(work, 1), &
255 : 1.0_dp, integral(i)%block(sgfa, sgfb), &
256 236175 : SIZE(integral(i)%block, 1))
257 :
258 : ELSE
259 :
260 : CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
261 : -1.0_dp, work(1, 1), SIZE(work, 1), &
262 : sphi_a(1, sgfa), SIZE(sphi_a, 1), &
263 : 1.0_dp, integral(i)%block(sgfb, sgfa), &
264 140430 : SIZE(integral(i)%block, 1))
265 :
266 : END IF
267 : ELSE
268 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
269 : 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
270 : work(1, 1), SIZE(work, 1), &
271 : 1.0_dp, integral(i)%block(sgfa, sgfb), &
272 27 : SIZE(integral(i)%block, 1))
273 : END IF
274 :
275 : END DO
276 :
277 : END DO
278 :
279 : END DO
280 :
281 : END DO
282 1164 : CALL neighbor_list_iterator_release(nl_iterator)
283 :
284 : ! *** Release work storage ***
285 :
286 1164 : DEALLOCATE (intab, work, integral, basis_set_list)
287 :
288 : ! *** Print the spin orbit matrix, if requested ***
289 :
290 : !IF (BTEST(cp_print_key_should_output(logger%iter_info,&
291 : ! qs_env%input,"DFT%PRINT%AO_MATRICES/LINEAR_MOMENTUM"),cp_p_file)) THEN
292 : ! iw = cp_print_key_unit_nr(logger,qs_env%input,"DFT%PRINT%AO_MATRICES/LINEA_MOMENTUM",&
293 : ! extension=".Log")
294 : ! CALL cp_dbcsr_write_sparse_matrix(matrix(1)%matrix,4,6,qs_env,para_env,output_unit=iw)
295 : ! CALL cp_dbcsr_write_sparse_matrix(matrix(2)%matrix,4,6,qs_env,para_env,output_unit=iw)
296 : ! CALL cp_dbcsr_write_sparse_matrix(matrix(3)%matrix,4,6,qs_env,para_env,output_unit=iw)
297 : ! CALL cp_print_key_finished_output(iw,logger,qs_env%input,&
298 : ! "DFT%PRINT%AO_MATRICES/LINEAR_MOMENTUM")
299 : !END IF
300 :
301 1164 : CALL timestop(handle)
302 :
303 3492 : END SUBROUTINE build_lin_mom_matrix
304 :
305 : ! **************************************************************************************************
306 : !> \brief Calculation of the primitive paramagnetic spin orbit integrals over
307 : !> Cartesian Gaussian-type functions.
308 : !> \param la_max ...
309 : !> \param la_min ...
310 : !> \param npgfa ...
311 : !> \param rpgfa ...
312 : !> \param zeta ...
313 : !> \param lb_max ...
314 : !> \param lb_min ...
315 : !> \param npgfb ...
316 : !> \param rpgfb ...
317 : !> \param zetb ...
318 : !> \param rab ...
319 : !> \param intab ...
320 : !> \param ldrr ...
321 : !> \param rr ...
322 : !> \date 02.03.2009
323 : !> \author VW
324 : !> \version 1.0
325 : ! **************************************************************************************************
326 251088 : SUBROUTINE lin_mom(la_max, la_min, npgfa, rpgfa, zeta, lb_max, lb_min, npgfb, rpgfb, zetb, &
327 125544 : rab, intab, ldrr, rr)
328 : INTEGER, INTENT(IN) :: la_max, la_min, npgfa
329 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: rpgfa, zeta
330 : INTEGER, INTENT(IN) :: lb_max, lb_min, npgfb
331 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: rpgfb, zetb
332 : REAL(KIND=dp), DIMENSION(3), INTENT(IN) :: rab
333 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT) :: intab
334 : INTEGER, INTENT(IN) :: ldrr
335 : REAL(dp), DIMENSION(0:ldrr-1, 0:ldrr-1, 3), &
336 : INTENT(INOUT) :: rr
337 :
338 : INTEGER :: ax, ay, az, bx, by, bz, coa, cob, i, &
339 : ipgf, j, jpgf, la, lb, ma, mb, na, nb
340 : REAL(dp) :: dab, dumx, dumy, dumz, f0, rab2, xhi, zet
341 : REAL(dp), DIMENSION(3) :: rap, rbp
342 :
343 : ! *** Calculate the distance of the centers a and c ***
344 :
345 125544 : rab2 = rab(1)**2 + rab(2)**2 + rab(3)**2
346 125544 : dab = SQRT(rab2)
347 :
348 : ! *** Loop over all pairs of primitive Gaussian-type functions ***
349 :
350 125544 : na = 0
351 :
352 434527 : DO ipgf = 1, npgfa
353 :
354 308983 : nb = 0
355 :
356 1217393 : DO jpgf = 1, npgfb
357 :
358 : ! *** Screening ***
359 :
360 908410 : IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) THEN
361 2225045 : DO j = nb + 1, nb + ncoset(lb_max)
362 7594668 : DO i = na + 1, na + ncoset(la_max)
363 5369623 : intab(i, j, 1) = 0.0_dp
364 5369623 : intab(i, j, 2) = 0.0_dp
365 7008533 : intab(i, j, 3) = 0.0_dp
366 : END DO
367 : END DO
368 586135 : nb = nb + ncoset(lb_max)
369 586135 : CYCLE
370 : END IF
371 :
372 : ! *** Calculate some prefactors ***
373 322275 : zet = zeta(ipgf) + zetb(jpgf)
374 322275 : xhi = zeta(ipgf)*zetb(jpgf)/zet
375 1289100 : rap = zetb(jpgf)*rab/zet
376 1289100 : rbp = -zeta(ipgf)*rab/zet
377 :
378 322275 : f0 = (pi/zet)**(1.5_dp)*EXP(-xhi*rab2)
379 :
380 : ! *** Calculate the recurrence relation ***
381 :
382 322275 : CALL os_rr_ovlp(rap, la_max + 1, rbp, lb_max, zet, ldrr, rr)
383 :
384 : ! *** Calculate the primitive linear momentum integrals ***
385 785705 : DO lb = lb_min, lb_max
386 1429435 : DO bx = 0, lb
387 1944738 : DO by = 0, lb - bx
388 837578 : bz = lb - bx - by
389 837578 : cob = coset(bx, by, bz)
390 837578 : mb = nb + cob
391 2801180 : DO la = la_min, la_max
392 4077634 : DO ax = 0, la
393 5813199 : DO ay = 0, la - ax
394 2573143 : az = la - ax - ay
395 2573143 : coa = coset(ax, ay, az)
396 2573143 : ma = na + coa
397 : !
398 : !
399 : ! (a|p_x|b) = 2*a*(a+1x|b) - N_x(a)*(a-1_x|b)
400 2573143 : dumx = 2.0_dp*zeta(ipgf)*rr(ax + 1, bx, 1)
401 2573143 : IF (ax > 0) dumx = dumx - REAL(ax, dp)*rr(ax - 1, bx, 1)
402 2573143 : intab(ma, mb, 1) = f0*dumx*rr(ay, by, 2)*rr(az, bz, 3)
403 : !
404 : ! (a|p_y|b)
405 2573143 : dumy = 2.0_dp*zeta(ipgf)*rr(ay + 1, by, 2)
406 2573143 : IF (ay > 0) dumy = dumy - REAL(ay, dp)*rr(ay - 1, by, 2)
407 2573143 : intab(ma, mb, 2) = f0*rr(ax, bx, 1)*dumy*rr(az, bz, 3)
408 : !
409 : ! (a|p_z|b)
410 2573143 : dumz = 2.0_dp*zeta(ipgf)*rr(az + 1, bz, 3)
411 2573143 : IF (az > 0) dumz = dumz - REAL(az, dp)*rr(az - 1, bz, 3)
412 4493327 : intab(ma, mb, 3) = f0*rr(ax, bx, 1)*rr(ay, by, 2)*dumz
413 : !
414 : END DO
415 : END DO
416 : END DO !la
417 :
418 : END DO
419 : END DO
420 : END DO !lb
421 :
422 631258 : nb = nb + ncoset(lb_max)
423 :
424 : END DO
425 :
426 434527 : na = na + ncoset(la_max)
427 :
428 : END DO
429 :
430 125544 : END SUBROUTINE lin_mom
431 :
432 : ! **************************************************************************************************
433 : !> \brief Calculation of the angular momentum matrix over
434 : !> Cartesian Gaussian functions.
435 : !> \param qs_env ...
436 : !> \param matrix ...
437 : !> \param rc ...
438 : !> \date 27.02.2009
439 : !> \author VW
440 : !> \version 1.0
441 : ! **************************************************************************************************
442 :
443 1250 : SUBROUTINE build_ang_mom_matrix(qs_env, matrix, rc)
444 :
445 : TYPE(qs_environment_type), POINTER :: qs_env
446 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix
447 : REAL(dp), DIMENSION(:), INTENT(IN) :: rc
448 :
449 : CHARACTER(len=*), PARAMETER :: routineN = 'build_ang_mom_matrix'
450 :
451 : INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
452 : ldai, maxco, maxlgto, maxsgf, ncoa, ncob, nkind, nseta, nsetb, sgfa, sgfb
453 1250 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, npgfa, &
454 1250 : npgfb, nsgfa, nsgfb
455 1250 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
456 : LOGICAL :: found, new_atom_b
457 : REAL(KIND=dp) :: dab, rab2
458 1250 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: work
459 1250 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: intab, rr_work
460 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rac, rbc
461 1250 : REAL(KIND=dp), DIMENSION(:), POINTER :: set_radius_a, set_radius_b
462 1250 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb
463 1250 : TYPE(block_p_type), ALLOCATABLE, DIMENSION(:) :: integral
464 : TYPE(cell_type), POINTER :: cell
465 1250 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
466 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
467 : TYPE(neighbor_list_iterator_p_type), &
468 1250 : DIMENSION(:), POINTER :: nl_iterator
469 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
470 1250 : POINTER :: sab_all
471 1250 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
472 1250 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
473 : TYPE(qs_kind_type), POINTER :: qs_kind
474 :
475 1250 : CALL timeset(routineN, handle)
476 :
477 : CALL get_qs_env(qs_env=qs_env, &
478 : qs_kind_set=qs_kind_set, &
479 : particle_set=particle_set, &
480 : sab_all=sab_all, &
481 1250 : cell=cell)
482 :
483 1250 : nkind = SIZE(qs_kind_set)
484 :
485 : ! *** Allocate work storage ***
486 :
487 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
488 : maxco=maxco, &
489 : maxlgto=maxlgto, &
490 1250 : maxsgf=maxsgf)
491 :
492 1250 : ldai = ncoset(maxlgto + 1)
493 1250 : CALL init_orbital_pointers(ldai)
494 :
495 18750 : ALLOCATE (rr_work(ldai, ldai, 3), intab(maxco, maxco, 3), work(maxco, maxsgf), integral(3))
496 1250 : rr_work(:, :, :) = 0.0_dp
497 1250 : intab(:, :, :) = 0.0_dp
498 1250 : work(:, :) = 0.0_dp
499 :
500 5796 : ALLOCATE (basis_set_list(nkind))
501 3296 : DO ikind = 1, nkind
502 2046 : qs_kind => qs_kind_set(ikind)
503 2046 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
504 3296 : IF (ASSOCIATED(basis_set_a)) THEN
505 2046 : basis_set_list(ikind)%gto_basis_set => basis_set_a
506 : ELSE
507 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
508 : END IF
509 : END DO
510 1250 : CALL neighbor_list_iterator_create(nl_iterator, sab_all)
511 94981 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
512 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
513 93731 : iatom=iatom, jatom=jatom, r=rab)
514 93731 : basis_set_a => basis_set_list(ikind)%gto_basis_set
515 93731 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
516 93731 : basis_set_b => basis_set_list(jkind)%gto_basis_set
517 93731 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
518 93731 : ra = pbc(particle_set(iatom)%r, cell)
519 : ! basis ikind
520 93731 : first_sgfa => basis_set_a%first_sgf
521 93731 : la_max => basis_set_a%lmax
522 93731 : la_min => basis_set_a%lmin
523 93731 : npgfa => basis_set_a%npgf
524 93731 : nseta = basis_set_a%nset
525 93731 : nsgfa => basis_set_a%nsgf_set
526 93731 : rpgfa => basis_set_a%pgf_radius
527 93731 : set_radius_a => basis_set_a%set_radius
528 93731 : sphi_a => basis_set_a%sphi
529 93731 : zeta => basis_set_a%zet
530 : ! basis jkind
531 93731 : first_sgfb => basis_set_b%first_sgf
532 93731 : lb_max => basis_set_b%lmax
533 93731 : lb_min => basis_set_b%lmin
534 93731 : npgfb => basis_set_b%npgf
535 93731 : nsetb = basis_set_b%nset
536 93731 : nsgfb => basis_set_b%nsgf_set
537 93731 : rpgfb => basis_set_b%pgf_radius
538 93731 : set_radius_b => basis_set_b%set_radius
539 93731 : sphi_b => basis_set_b%sphi
540 93731 : zetb => basis_set_b%zet
541 :
542 93731 : IF (inode == 1) last_jatom = 0
543 :
544 93731 : IF (jatom /= last_jatom) THEN
545 : new_atom_b = .TRUE.
546 : last_jatom = jatom
547 : ELSE
548 : new_atom_b = .FALSE.
549 : END IF
550 :
551 : IF (new_atom_b) THEN
552 : !IF (iatom <= jatom) THEN
553 5987 : irow = iatom
554 5987 : icol = jatom
555 : !ELSE
556 : ! irow = jatom
557 : ! icol = iatom
558 : !END IF
559 :
560 23948 : DO i = 1, 3
561 17961 : NULLIFY (INTEGRAL(i)%block)
562 : CALL dbcsr_get_block_p(matrix=matrix(i)%matrix, &
563 17961 : row=irow, col=icol, BLOCK=INTEGRAL(i)%block, found=found)
564 23948 : CPASSERT(ASSOCIATED(INTEGRAL(i)%block))
565 : END DO
566 : END IF
567 :
568 93731 : rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
569 93731 : dab = SQRT(rab2)
570 :
571 312058 : DO iset = 1, nseta
572 :
573 217077 : ncoa = npgfa(iset)*ncoset(la_max(iset))
574 217077 : sgfa = first_sgfa(1, iset)
575 :
576 837307 : DO jset = 1, nsetb
577 :
578 526499 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
579 :
580 : !IF(PRESENT(wancen)) THEN
581 : ! rc = wancen
582 201893 : rac = pbc(rc, ra, cell)
583 807572 : rbc = rac + rab
584 : !ELSE
585 : ! rc(1:3) = rb(1:3)
586 : ! rac(1:3) = -rab(1:3)
587 : ! rbc(1:3) = 0.0_dp
588 : !ENDIF
589 :
590 201893 : ncob = npgfb(jset)*ncoset(lb_max(jset))
591 201893 : sgfb = first_sgfb(1, jset)
592 :
593 : ! *** Calculate the primitive angular momentum integrals ***
594 :
595 : CALL ang_mom(la_max(iset), la_min(iset), npgfa(iset), &
596 : rpgfa(:, iset), zeta(:, iset), &
597 : lb_max(jset), lb_min(jset), npgfb(jset), &
598 : rpgfb(:, jset), zetb(:, jset), &
599 201893 : rab, rac, intab, SIZE(rr_work, 1), rr_work)
600 :
601 : ! *** Contraction step ***
602 :
603 1024649 : DO i = 1, 3
604 :
605 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
606 : 1.0_dp, intab(1, 1, i), SIZE(intab, 1), &
607 : sphi_b(1, sgfb), SIZE(sphi_b, 1), &
608 605679 : 0.0_dp, work(1, 1), SIZE(work, 1))
609 :
610 : !IF (iatom <= jatom) THEN
611 :
612 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
613 : 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
614 : work(1, 1), SIZE(work, 1), &
615 : 1.0_dp, integral(i)%block(sgfa, sgfb), &
616 1132178 : SIZE(integral(i)%block, 1))
617 :
618 : !ELSE
619 : !
620 : ! CALL dgemm("T","N",nsgfb(jset),nsgfa(iset),ncoa,&
621 : ! -1.0_dp,work(1,1),SIZE(work,1),&
622 : ! sphi_a(1,sgfa),SIZE(sphi_a,1),&
623 : ! 1.0_dp,integral(i)%block(sgfb,sgfa),&
624 : ! SIZE(integral(i)%block,1))
625 : !
626 : !ENDIF
627 :
628 : END DO
629 :
630 : END DO
631 :
632 : END DO
633 :
634 : END DO
635 1250 : CALL neighbor_list_iterator_release(nl_iterator)
636 :
637 : ! *** Release work storage ***
638 :
639 1250 : DEALLOCATE (intab, work, integral, basis_set_list)
640 :
641 : ! *** Print the spin orbit matrix, if requested ***
642 :
643 : !IF (BTEST(cp_print_key_should_output(logger%iter_info,&
644 : ! qs_env%input,"DFT%PRINT%AO_MATRICES/ANGULAR_MOMENTUM"),cp_p_file)) THEN
645 : ! iw = cp_print_key_unit_nr(logger,qs_env%input,"DFT%PRINT%AO_MATRICES/ANGULAR_MOMENTUM",&
646 : ! extension=".Log")
647 : ! CALL cp_dbcsr_write_sparse_matrix(matrix(1)%matrix,4,6,qs_env,para_env,output_unit=iw)
648 : ! CALL cp_dbcsr_write_sparse_matrix(matrix(2)%matrix,4,6,qs_env,para_env,output_unit=iw)
649 : ! CALL cp_dbcsr_write_sparse_matrix(matrix(3)%matrix,4,6,qs_env,para_env,output_unit=iw)
650 : ! CALL cp_print_key_finished_output(iw,logger,qs_env%input,&
651 : ! "DFT%PRINT%AO_MATRICES/ANGULAR_MOMENTUM")
652 : !END IF
653 :
654 1250 : CALL timestop(handle)
655 :
656 3750 : END SUBROUTINE build_ang_mom_matrix
657 :
658 : ! **************************************************************************************************
659 : !> \brief Calculation of the primitive paramagnetic spin orbit integrals over
660 : !> Cartesian Gaussian-type functions.
661 : !> \param la_max ...
662 : !> \param la_min ...
663 : !> \param npgfa ...
664 : !> \param rpgfa ...
665 : !> \param zeta ...
666 : !> \param lb_max ...
667 : !> \param lb_min ...
668 : !> \param npgfb ...
669 : !> \param rpgfb ...
670 : !> \param zetb ...
671 : !> \param rab ...
672 : !> \param rac ...
673 : !> \param intab ...
674 : !> \param ldrr ...
675 : !> \param rr ...
676 : !> \date 02.03.2009
677 : !> \author VW
678 : !> \version 1.0
679 : ! **************************************************************************************************
680 403786 : SUBROUTINE ang_mom(la_max, la_min, npgfa, rpgfa, zeta, lb_max, lb_min, npgfb, rpgfb, zetb, &
681 201893 : rab, rac, intab, ldrr, rr)
682 : INTEGER, INTENT(IN) :: la_max, la_min, npgfa
683 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: rpgfa, zeta
684 : INTEGER, INTENT(IN) :: lb_max, lb_min, npgfb
685 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: rpgfb, zetb
686 : REAL(KIND=dp), DIMENSION(3), INTENT(IN) :: rab, rac
687 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT) :: intab
688 : INTEGER, INTENT(IN) :: ldrr
689 : REAL(dp), DIMENSION(0:ldrr-1, 0:ldrr-1, 3), &
690 : INTENT(INOUT) :: rr
691 :
692 : INTEGER :: ax, ay, az, bx, by, bz, coa, cob, i, &
693 : ipgf, j, jpgf, la, lb, ma, mb, na, nb
694 : REAL(dp) :: dab, dumx, dumy, dumz, f0, rab2, xhi, zet
695 : REAL(dp), DIMENSION(3) :: rap, rbp
696 :
697 : ! *** Calculate the distance of the centers a and c ***
698 :
699 201893 : rab2 = rab(1)**2 + rab(2)**2 + rab(3)**2
700 201893 : dab = SQRT(rab2)
701 :
702 : ! *** Loop over all pairs of primitive Gaussian-type functions ***
703 :
704 201893 : na = 0
705 :
706 676304 : DO ipgf = 1, npgfa
707 :
708 474411 : nb = 0
709 :
710 1742562 : DO jpgf = 1, npgfb
711 :
712 : ! *** Screening ***
713 :
714 1268151 : IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) THEN
715 3336529 : DO j = nb + 1, nb + ncoset(lb_max)
716 12446889 : DO i = na + 1, na + ncoset(la_max)
717 9110360 : intab(i, j, 1) = 0.0_dp
718 9110360 : intab(i, j, 2) = 0.0_dp
719 11620957 : intab(i, j, 3) = 0.0_dp
720 : END DO
721 : END DO
722 825932 : nb = nb + ncoset(lb_max)
723 825932 : CYCLE
724 : END IF
725 :
726 : ! *** Calculate some prefactors ***
727 442219 : zet = zeta(ipgf) + zetb(jpgf)
728 442219 : xhi = zeta(ipgf)*zetb(jpgf)/zet
729 1768876 : rap = zetb(jpgf)*rab/zet
730 1768876 : rbp = -zeta(ipgf)*rab/zet
731 :
732 442219 : f0 = (pi/zet)**(1.5_dp)*EXP(-xhi*rab2)
733 :
734 : ! *** Calculate the recurrence relation ***
735 :
736 442219 : CALL os_rr_ovlp(rap, la_max + 1, rbp, lb_max, zet, ldrr, rr)
737 :
738 : ! *** Calculate the primitive Fermi contact integrals ***
739 :
740 1087122 : DO lb = lb_min, lb_max
741 2011607 : DO bx = 0, lb
742 2802912 : DO by = 0, lb - bx
743 1233524 : bz = lb - bx - by
744 1233524 : cob = coset(bx, by, bz)
745 1233524 : mb = nb + cob
746 4112005 : DO la = la_min, la_max
747 6109494 : DO ax = 0, la
748 8873886 : DO ay = 0, la - ax
749 3997916 : az = la - ax - ay
750 3997916 : coa = coset(ax, ay, az)
751 3997916 : ma = na + coa
752 : !
753 3997916 : dumx = -2.0_dp*zeta(ipgf)*rr(ax + 1, bx, 1)
754 3997916 : dumy = -2.0_dp*zeta(ipgf)*rr(ay + 1, by, 2)
755 3997916 : dumz = -2.0_dp*zeta(ipgf)*rr(az + 1, bz, 3)
756 3997916 : IF (ax > 0) dumx = dumx + REAL(ax, dp)*rr(ax - 1, bx, 1)
757 3997916 : IF (ay > 0) dumy = dumy + REAL(ay, dp)*rr(ay - 1, by, 2)
758 3997916 : IF (az > 0) dumz = dumz + REAL(az, dp)*rr(az - 1, bz, 3)
759 : !
760 : ! (a|l_z|b)
761 : intab(ma, mb, 1) = -f0*rr(ax, bx, 1)*( &
762 : & (rr(ay + 1, by, 2) + rac(2)*rr(ay, by, 2))*dumz &
763 3997916 : & - (rr(az + 1, bz, 3) + rac(3)*rr(az, bz, 3))*dumy)
764 : !
765 : ! (a|l_y|b)
766 : intab(ma, mb, 2) = -f0*rr(ay, by, 2)*( &
767 : & (rr(az + 1, bz, 3) + rac(3)*rr(az, bz, 3))*dumx &
768 3997916 : & - (rr(ax + 1, bx, 1) + rac(1)*rr(ax, bx, 1))*dumz)
769 : !
770 : ! (a|l_z|b)
771 : intab(ma, mb, 3) = -f0*rr(az, bz, 3)*( &
772 : & (rr(ax + 1, bx, 1) + rac(1)*rr(ax, bx, 1))*dumy &
773 6919890 : & - (rr(ay + 1, by, 2) + rac(2)*rr(ay, by, 2))*dumx)
774 : !
775 : END DO
776 : END DO
777 : END DO !la
778 :
779 : END DO
780 : END DO
781 : END DO !lb
782 :
783 916630 : nb = nb + ncoset(lb_max)
784 :
785 : END DO
786 :
787 676304 : na = na + ncoset(la_max)
788 :
789 : END DO
790 :
791 201893 : END SUBROUTINE ang_mom
792 :
793 : ! **************************************************************************************************
794 : !> \brief Calculation of the components of the dipole operator in the velocity form
795 : !> The elements of the sparse matrices are the integrals in the
796 : !> basis functions
797 : !> \param op matrix representation of the p operator
798 : !> calculated in terms of the contracted basis functions
799 : !> \param qs_env environment for the lists and the basis sets
800 : !> \param minimum_image take into account only the first neighbors in the lists
801 : !> \par History
802 : !> 06.2005 created [MI]
803 : !> \author MI
804 : ! **************************************************************************************************
805 :
806 86 : SUBROUTINE p_xyz_ao(op, qs_env, minimum_image)
807 :
808 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: op
809 : TYPE(qs_environment_type), POINTER :: qs_env
810 : LOGICAL, INTENT(IN), OPTIONAL :: minimum_image
811 :
812 : CHARACTER(len=*), PARAMETER :: routineN = 'p_xyz_ao'
813 :
814 : INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
815 : ldab, ldsa, ldsb, ldwork, maxl, ncoa, ncob, nkind, nseta, nsetb, sgfa, sgfb
816 86 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, npgfa, &
817 86 : npgfb, nsgfa, nsgfb
818 86 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
819 : LOGICAL :: found, my_minimum_image, new_atom_b
820 : REAL(KIND=dp) :: alpha, dab, Lxo2, Lyo2, Lzo2, rab2
821 : REAL(KIND=dp), DIMENSION(3) :: ra, rab
822 86 : REAL(KIND=dp), DIMENSION(:), POINTER :: set_radius_a, set_radius_b
823 86 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: rpgfa, rpgfb, sphi_a, sphi_b, work, &
824 86 : zeta, zetb
825 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: difab
826 86 : TYPE(block_p_type), DIMENSION(:), POINTER :: op_dip
827 : TYPE(cell_type), POINTER :: cell
828 86 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
829 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
830 : TYPE(neighbor_list_iterator_p_type), &
831 86 : DIMENSION(:), POINTER :: nl_iterator
832 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
833 86 : POINTER :: sab_orb
834 86 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
835 86 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
836 : TYPE(qs_kind_type), POINTER :: qs_kind
837 :
838 86 : CALL timeset(routineN, handle)
839 :
840 86 : NULLIFY (qs_kind, qs_kind_set)
841 86 : NULLIFY (cell, particle_set)
842 86 : NULLIFY (sab_orb)
843 86 : NULLIFY (difab, op_dip, work)
844 86 : NULLIFY (la_max, la_min, lb_max, lb_min, npgfa, npgfb, nsgfa, nsgfb)
845 86 : NULLIFY (set_radius_a, set_radius_b, rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb)
846 :
847 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
848 : cell=cell, particle_set=particle_set, &
849 86 : sab_orb=sab_orb)
850 :
851 86 : nkind = SIZE(qs_kind_set)
852 :
853 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
854 86 : maxco=ldwork, maxlgto=maxl)
855 :
856 86 : my_minimum_image = .FALSE.
857 86 : IF (PRESENT(minimum_image)) THEN
858 44 : my_minimum_image = minimum_image
859 176 : Lxo2 = SQRT(SUM(cell%hmat(:, 1)**2))/2.0_dp
860 176 : Lyo2 = SQRT(SUM(cell%hmat(:, 2)**2))/2.0_dp
861 176 : Lzo2 = SQRT(SUM(cell%hmat(:, 3)**2))/2.0_dp
862 : END IF
863 :
864 86 : ldab = ldwork
865 :
866 430 : ALLOCATE (difab(ldab, ldab, 3))
867 81272 : difab(1:ldab, 1:ldab, 1:3) = 0.0_dp
868 344 : ALLOCATE (work(ldwork, ldwork))
869 27062 : work(1:ldwork, 1:ldwork) = 0.0_dp
870 344 : ALLOCATE (op_dip(3))
871 :
872 344 : DO i = 1, 3
873 344 : NULLIFY (op_dip(i)%block)
874 : END DO
875 :
876 398 : ALLOCATE (basis_set_list(nkind))
877 226 : DO ikind = 1, nkind
878 140 : qs_kind => qs_kind_set(ikind)
879 140 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
880 226 : IF (ASSOCIATED(basis_set_a)) THEN
881 140 : basis_set_list(ikind)%gto_basis_set => basis_set_a
882 : ELSE
883 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
884 : END IF
885 : END DO
886 86 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
887 9930 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
888 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
889 9844 : iatom=iatom, jatom=jatom, r=rab)
890 9844 : basis_set_a => basis_set_list(ikind)%gto_basis_set
891 9844 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
892 9844 : basis_set_b => basis_set_list(jkind)%gto_basis_set
893 9844 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
894 9844 : ra = pbc(particle_set(iatom)%r, cell)
895 : ! basis ikind
896 9844 : first_sgfa => basis_set_a%first_sgf
897 9844 : la_max => basis_set_a%lmax
898 9844 : la_min => basis_set_a%lmin
899 9844 : npgfa => basis_set_a%npgf
900 9844 : nseta = basis_set_a%nset
901 9844 : nsgfa => basis_set_a%nsgf_set
902 9844 : rpgfa => basis_set_a%pgf_radius
903 9844 : set_radius_a => basis_set_a%set_radius
904 9844 : sphi_a => basis_set_a%sphi
905 9844 : zeta => basis_set_a%zet
906 : ! basis jkind
907 9844 : first_sgfb => basis_set_b%first_sgf
908 9844 : lb_max => basis_set_b%lmax
909 9844 : lb_min => basis_set_b%lmin
910 9844 : npgfb => basis_set_b%npgf
911 9844 : nsetb = basis_set_b%nset
912 9844 : nsgfb => basis_set_b%nsgf_set
913 9844 : rpgfb => basis_set_b%pgf_radius
914 9844 : set_radius_b => basis_set_b%set_radius
915 9844 : sphi_b => basis_set_b%sphi
916 9844 : zetb => basis_set_b%zet
917 :
918 9844 : IF (inode == 1) THEN
919 384 : last_jatom = 0
920 384 : alpha = 1.0_dp
921 : END IF
922 9844 : ldsa = SIZE(sphi_a, 1)
923 9844 : ldsb = SIZE(sphi_b, 1)
924 :
925 9844 : IF (my_minimum_image) THEN
926 8374 : IF (ABS(rab(1)) > Lxo2 .OR. ABS(rab(2)) > Lyo2 .OR. ABS(rab(3)) > Lzo2) CYCLE
927 : END IF
928 :
929 6380 : IF (jatom /= last_jatom) THEN
930 : new_atom_b = .TRUE.
931 : last_jatom = jatom
932 : ELSE
933 : new_atom_b = .FALSE.
934 : END IF
935 :
936 : IF (new_atom_b) THEN
937 4950 : IF (iatom <= jatom) THEN
938 2551 : irow = iatom
939 2551 : icol = jatom
940 2551 : alpha = 1.0_dp
941 : ELSE
942 2399 : irow = jatom
943 2399 : icol = iatom
944 2399 : IF (dbcsr_get_matrix_type(op(1)%matrix) == dbcsr_type_antisymmetric) THEN
945 : !IF(op(1)%matrix%symmetry=="antisymmetric") THEN
946 4798 : alpha = -1.0_dp
947 : END IF
948 : END IF
949 :
950 19800 : DO i = 1, 3
951 14850 : NULLIFY (op_dip(i)%block)
952 : CALL dbcsr_get_block_p(matrix=op(i)%matrix, &
953 14850 : row=irow, col=icol, block=op_dip(i)%block, found=found)
954 19800 : CPASSERT(ASSOCIATED(op_dip(i)%block))
955 : END DO
956 : END IF ! new_atom_b
957 6380 : rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
958 6380 : dab = SQRT(rab2)
959 :
960 24093 : DO iset = 1, nseta
961 :
962 17627 : ncoa = npgfa(iset)*ncoset(la_max(iset))
963 17627 : sgfa = first_sgfa(1, iset)
964 :
965 80461 : DO jset = 1, nsetb
966 :
967 52990 : ncob = npgfb(jset)*ncoset(lb_max(jset))
968 52990 : sgfb = first_sgfb(1, jset)
969 :
970 70617 : IF (set_radius_a(iset) + set_radius_b(jset) >= dab) THEN
971 :
972 : ! *** Calculate the primitive overlap integrals ***
973 : CALL diffop(la_max(iset), npgfa(iset), zeta(:, iset), &
974 : rpgfa(:, iset), la_min(iset), lb_max(jset), npgfb(jset), &
975 23477 : zetb(:, jset), rpgfb(:, jset), lb_min(jset), rab, difab)
976 :
977 : ! *** Contraction ***
978 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
979 : alpha, difab(1, 1, 1), ldab, sphi_b(1, sgfb), ldsb, &
980 23477 : 0.0_dp, work(1, 1), ldwork)
981 23477 : IF (iatom <= jatom) THEN
982 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
983 : 1.0_dp, sphi_a(1, sgfa), ldsa, &
984 : work(1, 1), ldwork, &
985 : 1.0_dp, op_dip(1)%block(sgfa, sgfb), &
986 13207 : SIZE(op_dip(1)%block, 1))
987 :
988 : ELSE
989 : CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
990 : 1.0_dp, work(1, 1), ldwork, &
991 : sphi_a(1, sgfa), ldsa, &
992 : 1.0_dp, op_dip(1)%block(sgfb, sgfa), &
993 10270 : SIZE(op_dip(1)%block, 1))
994 :
995 : END IF
996 :
997 : ! *** Contraction ***
998 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
999 : alpha, difab(1, 1, 2), ldab, sphi_b(1, sgfb), ldsb, &
1000 23477 : 0.0_dp, work(1, 1), ldwork)
1001 23477 : IF (iatom <= jatom) THEN
1002 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
1003 : 1.0_dp, sphi_a(1, sgfa), ldsa, &
1004 : work(1, 1), ldwork, &
1005 : 1.0_dp, op_dip(2)%block(sgfa, sgfb), &
1006 13207 : SIZE(op_dip(2)%block, 1))
1007 : ELSE
1008 : CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
1009 : 1.0_dp, work(1, 1), ldwork, &
1010 : sphi_a(1, sgfa), ldsa, &
1011 : 1.0_dp, op_dip(2)%block(sgfb, sgfa), &
1012 10270 : SIZE(op_dip(2)%block, 1))
1013 : END IF
1014 :
1015 : ! *** Contraction ***
1016 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
1017 : alpha, difab(1, 1, 3), ldab, sphi_b(1, sgfb), ldsb, &
1018 23477 : 0.0_dp, work(1, 1), ldwork)
1019 23477 : IF (iatom <= jatom) THEN
1020 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
1021 : 1.0_dp, sphi_a(1, sgfa), ldsa, &
1022 : work(1, 1), ldwork, &
1023 : 1.0_dp, op_dip(3)%block(sgfa, sgfb), &
1024 13207 : SIZE(op_dip(3)%block, 1))
1025 : ELSE
1026 : CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
1027 : 1.0_dp, work(1, 1), ldwork, &
1028 : sphi_a(1, sgfa), ldsa, &
1029 : 1.0_dp, op_dip(3)%block(sgfb, sgfa), &
1030 10270 : SIZE(op_dip(3)%block, 1))
1031 : END IF
1032 : END IF ! >= dab
1033 :
1034 : END DO ! jset
1035 :
1036 : END DO ! iset
1037 :
1038 : END DO
1039 86 : CALL neighbor_list_iterator_release(nl_iterator)
1040 :
1041 344 : DO i = 1, 3
1042 344 : NULLIFY (op_dip(i)%block)
1043 : END DO
1044 86 : DEALLOCATE (op_dip)
1045 :
1046 86 : DEALLOCATE (difab, work, basis_set_list)
1047 :
1048 86 : CALL timestop(handle)
1049 :
1050 172 : END SUBROUTINE p_xyz_ao
1051 :
1052 : ! **************************************************************************************************
1053 : !> \brief Calculation of the components of the dipole operator in the length form
1054 : !> by taking the relative position operator r-Rc, with respect a reference point Rc
1055 : !> Probably it does not work for PBC, or maybe yes if the wfn are
1056 : !> sufficiently localized
1057 : !> The elements of the sparse matrices are the integrals in the
1058 : !> basis functions
1059 : !> \param op matrix representation of the p operator
1060 : !> calculated in terms of the contracted basis functions
1061 : !> \param qs_env environment for the lists and the basis sets
1062 : !> \param rc reference vector position
1063 : !> \param order maximum order of the momentum, for the dipole order = 1, order = -2 for quad only
1064 : !> \param minimum_image take into account only the first neighbors in the lists
1065 : !> \param soft ...
1066 : !> \par History
1067 : !> 03.2006 created [MI]
1068 : !> 06.2019 added quarupole only option (A.Bussy)
1069 : !> \author MI
1070 : ! **************************************************************************************************
1071 :
1072 60 : SUBROUTINE rRc_xyz_ao(op, qs_env, rc, order, minimum_image, soft)
1073 :
1074 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: op
1075 : TYPE(qs_environment_type), POINTER :: qs_env
1076 : REAL(dp) :: Rc(3)
1077 : INTEGER, INTENT(IN) :: order
1078 : LOGICAL, INTENT(IN), OPTIONAL :: minimum_image, soft
1079 :
1080 : CHARACTER(len=*), PARAMETER :: routineN = 'rRc_xyz_ao'
1081 :
1082 : CHARACTER(LEN=default_string_length) :: basis_type
1083 : INTEGER :: handle, iatom, icol, ikind, imom, inode, irow, iset, jatom, jkind, jset, &
1084 : last_jatom, ldab, ldsa, ldsb, ldwork, M_dim, maxl, ncoa, ncob, nkind, nseta, nsetb, sgfa, &
1085 : sgfb, smom
1086 60 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, npgfa, npgfb, &
1087 60 : nsgfa, nsgfb
1088 60 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
1089 : LOGICAL :: found, my_minimum_image, my_soft, &
1090 : new_atom_b
1091 : REAL(KIND=dp) :: dab, Lxo2, Lyo2, Lzo2, rab2
1092 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rac, rb, rbc
1093 60 : REAL(KIND=dp), DIMENSION(:), POINTER :: set_radius_a, set_radius_b
1094 60 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: rpgfa, rpgfb, sphi_a, sphi_b, work, &
1095 60 : zeta, zetb
1096 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: mab
1097 60 : TYPE(block_p_type), DIMENSION(:), POINTER :: op_dip
1098 : TYPE(cell_type), POINTER :: cell
1099 60 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
1100 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
1101 : TYPE(neighbor_list_iterator_p_type), &
1102 60 : DIMENSION(:), POINTER :: nl_iterator
1103 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1104 60 : POINTER :: sab_orb
1105 60 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1106 60 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1107 : TYPE(qs_kind_type), POINTER :: qs_kind
1108 :
1109 60 : CALL timeset(routineN, handle)
1110 :
1111 60 : NULLIFY (qs_kind, qs_kind_set)
1112 60 : NULLIFY (cell, particle_set)
1113 60 : NULLIFY (sab_orb)
1114 60 : NULLIFY (mab, op_dip, work)
1115 60 : NULLIFY (la_max, la_min, lb_max, npgfa, npgfb, nsgfa, nsgfb)
1116 60 : NULLIFY (set_radius_a, set_radius_b, rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb)
1117 :
1118 60 : my_soft = .FALSE.
1119 60 : IF (PRESENT(soft)) my_soft = soft
1120 28 : IF (my_soft) THEN
1121 0 : basis_type = "ORB_SOFT"
1122 : ELSE
1123 60 : basis_type = "ORB"
1124 : END IF
1125 :
1126 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
1127 60 : cell=cell, particle_set=particle_set, sab_orb=sab_orb)
1128 :
1129 60 : nkind = SIZE(qs_kind_set)
1130 :
1131 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
1132 60 : maxco=ldwork, maxlgto=maxl)
1133 :
1134 60 : my_minimum_image = .FALSE.
1135 60 : IF (PRESENT(minimum_image)) THEN
1136 58 : my_minimum_image = minimum_image
1137 232 : Lxo2 = SQRT(SUM(cell%hmat(:, 1)**2))/2.0_dp
1138 232 : Lyo2 = SQRT(SUM(cell%hmat(:, 2)**2))/2.0_dp
1139 232 : Lzo2 = SQRT(SUM(cell%hmat(:, 3)**2))/2.0_dp
1140 : END IF
1141 :
1142 60 : ldab = ldwork
1143 :
1144 60 : smom = 1
1145 60 : IF (order == -2) smom = 4
1146 60 : M_dim = ncoset(ABS(order)) - 1
1147 60 : CPASSERT(M_dim <= SIZE(op, 1))
1148 :
1149 300 : ALLOCATE (mab(ldab, ldab, 1:M_dim))
1150 46032 : mab(1:ldab, 1:ldab, 1:M_dim) = 0.0_dp
1151 240 : ALLOCATE (work(ldwork, ldwork))
1152 15324 : work(1:ldwork, 1:ldwork) = 0.0_dp
1153 360 : ALLOCATE (op_dip(smom:M_dim))
1154 :
1155 240 : DO imom = smom, M_dim
1156 240 : NULLIFY (op_dip(imom)%block)
1157 : END DO
1158 :
1159 282 : ALLOCATE (basis_set_list(nkind))
1160 162 : DO ikind = 1, nkind
1161 102 : qs_kind => qs_kind_set(ikind)
1162 102 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
1163 162 : IF (ASSOCIATED(basis_set_a)) THEN
1164 102 : basis_set_list(ikind)%gto_basis_set => basis_set_a
1165 : ELSE
1166 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
1167 : END IF
1168 : END DO
1169 60 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
1170 462 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
1171 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
1172 402 : iatom=iatom, jatom=jatom, r=rab)
1173 402 : basis_set_a => basis_set_list(ikind)%gto_basis_set
1174 402 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
1175 402 : basis_set_b => basis_set_list(jkind)%gto_basis_set
1176 402 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
1177 402 : ra = pbc(particle_set(iatom)%r, cell)
1178 : ! basis ikind
1179 402 : first_sgfa => basis_set_a%first_sgf
1180 402 : la_max => basis_set_a%lmax
1181 402 : la_min => basis_set_a%lmin
1182 402 : npgfa => basis_set_a%npgf
1183 402 : nseta = basis_set_a%nset
1184 402 : nsgfa => basis_set_a%nsgf_set
1185 402 : rpgfa => basis_set_a%pgf_radius
1186 402 : set_radius_a => basis_set_a%set_radius
1187 402 : sphi_a => basis_set_a%sphi
1188 402 : zeta => basis_set_a%zet
1189 : ! basis jkind
1190 402 : first_sgfb => basis_set_b%first_sgf
1191 402 : lb_max => basis_set_b%lmax
1192 402 : npgfb => basis_set_b%npgf
1193 402 : nsetb = basis_set_b%nset
1194 402 : nsgfb => basis_set_b%nsgf_set
1195 402 : rpgfb => basis_set_b%pgf_radius
1196 402 : set_radius_b => basis_set_b%set_radius
1197 402 : sphi_b => basis_set_b%sphi
1198 402 : zetb => basis_set_b%zet
1199 :
1200 402 : ldsa = SIZE(sphi_a, 1)
1201 402 : ldsb = SIZE(sphi_b, 1)
1202 402 : IF (inode == 1) last_jatom = 0
1203 :
1204 402 : IF (my_minimum_image) THEN
1205 121 : IF (ABS(rab(1)) > Lxo2 .OR. ABS(rab(2)) > Lyo2 .OR. ABS(rab(3)) > Lzo2) CYCLE
1206 : END IF
1207 :
1208 1600 : rb = rab + ra
1209 :
1210 400 : IF (jatom /= last_jatom) THEN
1211 : new_atom_b = .TRUE.
1212 : last_jatom = jatom
1213 : ELSE
1214 : new_atom_b = .FALSE.
1215 : END IF
1216 :
1217 : IF (new_atom_b) THEN
1218 151 : IF (iatom <= jatom) THEN
1219 100 : irow = iatom
1220 100 : icol = jatom
1221 : ELSE
1222 51 : irow = jatom
1223 51 : icol = iatom
1224 : END IF
1225 :
1226 604 : DO imom = smom, M_dim
1227 453 : NULLIFY (op_dip(imom)%block)
1228 : CALL dbcsr_get_block_p(matrix=op(imom)%matrix, &
1229 453 : row=irow, col=icol, block=op_dip(imom)%block, found=found)
1230 604 : CPASSERT(ASSOCIATED(op_dip(imom)%block))
1231 : END DO ! imom
1232 : END IF ! new_atom_b
1233 :
1234 400 : rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
1235 400 : dab = SQRT(rab2)
1236 :
1237 1412 : DO iset = 1, nseta
1238 :
1239 952 : ncoa = npgfa(iset)*ncoset(la_max(iset))
1240 952 : sgfa = first_sgfa(1, iset)
1241 :
1242 3856 : DO jset = 1, nsetb
1243 :
1244 2502 : ncob = npgfb(jset)*ncoset(lb_max(jset))
1245 2502 : sgfb = first_sgfb(1, jset)
1246 :
1247 3454 : IF (set_radius_a(iset) + set_radius_b(jset) >= dab) THEN
1248 :
1249 1921 : rac = pbc(rc, ra, cell)
1250 1921 : rbc = pbc(rc, rb, cell)
1251 :
1252 : ! *** Calculate the primitive overlap integrals ***
1253 : CALL moment(la_max(iset), npgfa(iset), zeta(:, iset), &
1254 : rpgfa(:, iset), la_min(iset), &
1255 : lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), &
1256 1921 : ABS(order), rac, rbc, mab)
1257 :
1258 7684 : DO imom = smom, M_dim
1259 : ! *** Contraction ***
1260 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
1261 : 1.0_dp, mab(1, 1, imom), ldab, sphi_b(1, sgfb), ldsb, &
1262 5763 : 0.0_dp, work(1, 1), ldwork)
1263 7684 : IF (iatom <= jatom) THEN
1264 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
1265 : 1.0_dp, sphi_a(1, sgfa), ldsa, &
1266 : work(1, 1), ldwork, &
1267 : 1.0_dp, op_dip(imom)%block(sgfa, sgfb), &
1268 4215 : SIZE(op_dip(imom)%block, 1))
1269 : ELSE
1270 : CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
1271 : 1.0_dp, work(1, 1), ldwork, &
1272 : sphi_a(1, sgfa), ldsa, &
1273 : 1.0_dp, op_dip(imom)%block(sgfb, sgfa), &
1274 1548 : SIZE(op_dip(imom)%block, 1))
1275 : END IF
1276 :
1277 : END DO ! imom
1278 : END IF ! >= dab
1279 :
1280 : END DO ! jset
1281 :
1282 : END DO ! iset
1283 :
1284 : END DO
1285 60 : CALL neighbor_list_iterator_release(nl_iterator)
1286 :
1287 240 : DO imom = smom, M_dim
1288 240 : NULLIFY (op_dip(imom)%block)
1289 : END DO
1290 60 : DEALLOCATE (op_dip)
1291 :
1292 60 : DEALLOCATE (mab, work, basis_set_list)
1293 :
1294 60 : CALL timestop(handle)
1295 :
1296 120 : END SUBROUTINE rRc_xyz_ao
1297 :
1298 : ! **************************************************************************************************
1299 : !> \brief Calculation of the multipole operators integrals
1300 : !> and of its derivatives of the type
1301 : !> [\mu | op | d(\nu)/dR(\nu)]-[d(\mu)/dR(\mu)| op | \nu]
1302 : !> by taking the relative position operator r-Rc, with respect a reference point Rc
1303 : !> The derivative are with respect to the primitive position,
1304 : !> The multipole operator is symmetric and if it does not depend on R(\mu) or R(\nu)
1305 : !> therefore [\mu | op | d(\nu)/dR(\nu)] = -[d(\mu)/dR(\mu)| op | \nu]
1306 : !> [\mu|op|d(\nu)/dR]-[d(\mu)/dR|op|\nu]=2[\mu|op|d(\nu)/dR]
1307 : !> When it is not the case a correction term is needed
1308 : !>
1309 : !> The momentum operator [\mu|M|\nu] is symmetric, the number of components is
1310 : !> determined by the order: 3 for order 1 (x,y,x), 9 for order 2(xx,xy,xz,yy,yz,zz)
1311 : !> The derivative of the type [\mu | op | d(\nu)/dR_i(\nu)], where
1312 : !> i indicates the cartesian direction, is antisymmetric only when
1313 : !> the no component M =(r_i) or (r_i r_j) is in the same cartesian
1314 : !> direction of the derivative, indeed
1315 : !> d([\mu|M|\nu])/dr_i = [d(\mu)/dr_i|M|\nu] + [\mu|M|d(\nu)/dr_i] + [\mu |d(M)/dr_i|\nu]
1316 : !> d([\mu|M|\nu])/dr_i = -[d(\mu)/dR_i(\mu)|M|\nu] -[\mu|M|d(\nu)/dR_i(\nu)] + [\mu |d(M)/dr_i|\nu]
1317 : !> Therefore we cannot use an antisymmetric matrix
1318 : !>
1319 : !> The same holds for the derivative with respect to the electronic position r
1320 : !> taking into account that [\mu|op|d(\nu)/dR] = -[\mu|op|d(\nu)/dr]
1321 : !> \param op matrix representation of the p operator
1322 : !> calculated in terms of the contracted basis functions
1323 : !> \param op_der ...
1324 : !> \param qs_env environment for the lists and the basis sets
1325 : !> \param rc reference vector position
1326 : !> \param order maximum order of the momentum, for the dipole order = 1
1327 : !> \param minimum_image take into account only the first neighbors in the lists
1328 : !> \param soft ...
1329 : !> \par History
1330 : !> 03.2006 created [MI]
1331 : !> \author MI
1332 : !> \note
1333 : !> Probably it does not work for PBC, or maybe yes if the wfn are
1334 : !> sufficiently localized
1335 : !> The elements of the sparse matrices are the integrals in the
1336 : !> basis functions
1337 : ! **************************************************************************************************
1338 3750 : SUBROUTINE rRc_xyz_der_ao(op, op_der, qs_env, rc, order, minimum_image, soft)
1339 :
1340 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: op
1341 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: op_der
1342 : TYPE(qs_environment_type), POINTER :: qs_env
1343 : REAL(dp) :: Rc(3)
1344 : INTEGER, INTENT(IN) :: order
1345 : LOGICAL, INTENT(IN), OPTIONAL :: minimum_image, soft
1346 :
1347 : CHARACTER(len=*), PARAMETER :: routineN = 'rRc_xyz_der_ao'
1348 :
1349 : CHARACTER(LEN=default_string_length) :: basis_type
1350 : INTEGER :: handle, i, iatom, icol, idir, ikind, imom, inode, ipgf, irow, iset, j, jatom, &
1351 : jkind, jpgf, jset, last_jatom, lda_min, ldab, ldb_min, ldsa, ldsb, ldwork, M_dim, maxl, &
1352 : na, nb, ncoa, ncob, nda, ndb, nkind, nseta, nsetb, sgfa, sgfb
1353 3750 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, npgfa, &
1354 3750 : npgfb, nsgfa, nsgfb
1355 3750 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
1356 : LOGICAL :: my_minimum_image, my_soft, new_atom_b, &
1357 : op_der_found, op_found
1358 : REAL(KIND=dp) :: alpha, alpha_der, dab, Lxo2, Lyo2, Lzo2, &
1359 : rab2
1360 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rac, rb, rbc
1361 3750 : REAL(KIND=dp), DIMENSION(:), POINTER :: set_radius_a, set_radius_b
1362 3750 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: rpgfa, rpgfb, sphi_a, sphi_b, work, &
1363 3750 : zeta, zetb
1364 3750 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: mab, mab_tmp
1365 : REAL(KIND=dp), DIMENSION(:, :, :, :), POINTER :: difmab
1366 3750 : TYPE(block_p_type), DIMENSION(:), POINTER :: op_dip
1367 3750 : TYPE(block_p_type), DIMENSION(:, :), POINTER :: op_dip_der
1368 : TYPE(cell_type), POINTER :: cell
1369 3750 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
1370 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
1371 : TYPE(neighbor_list_iterator_p_type), &
1372 3750 : DIMENSION(:), POINTER :: nl_iterator
1373 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1374 3750 : POINTER :: sab_all
1375 3750 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1376 3750 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1377 : TYPE(qs_kind_type), POINTER :: qs_kind
1378 :
1379 3750 : CALL timeset(routineN, handle)
1380 :
1381 3750 : CPASSERT(ASSOCIATED(op))
1382 3750 : CPASSERT(ASSOCIATED(op_der))
1383 : !IF(.NOT.op_sm_der(1,1)%matrix%symmetry=="none") THEN
1384 3750 : CPASSERT(dbcsr_get_matrix_type(op_der(1, 1)%matrix) == dbcsr_type_no_symmetry)
1385 :
1386 3750 : NULLIFY (qs_kind, qs_kind_set)
1387 3750 : NULLIFY (cell, particle_set)
1388 3750 : NULLIFY (sab_all)
1389 3750 : NULLIFY (difmab, mab, mab_tmp)
1390 3750 : NULLIFY (op_dip, op_dip_der, work)
1391 3750 : NULLIFY (la_max, la_min, lb_max, lb_min, npgfa, npgfb, nsgfa, nsgfb)
1392 3750 : NULLIFY (set_radius_a, set_radius_b, rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb)
1393 :
1394 3750 : my_soft = .FALSE.
1395 3750 : IF (PRESENT(soft)) my_soft = soft
1396 3750 : IF (my_soft) THEN
1397 2022 : basis_type = "ORB_SOFT"
1398 : ELSE
1399 1728 : basis_type = "ORB"
1400 : END IF
1401 :
1402 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
1403 : cell=cell, particle_set=particle_set, &
1404 3750 : sab_all=sab_all)
1405 :
1406 3750 : nkind = SIZE(qs_kind_set)
1407 :
1408 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
1409 3750 : maxco=ldwork, maxlgto=maxl)
1410 :
1411 3750 : my_minimum_image = .FALSE.
1412 3750 : IF (PRESENT(minimum_image)) THEN
1413 3750 : my_minimum_image = minimum_image
1414 15000 : Lxo2 = SQRT(SUM(cell%hmat(:, 1)**2))/2.0_dp
1415 15000 : Lyo2 = SQRT(SUM(cell%hmat(:, 2)**2))/2.0_dp
1416 15000 : Lzo2 = SQRT(SUM(cell%hmat(:, 3)**2))/2.0_dp
1417 : END IF
1418 :
1419 3750 : ldab = ldwork
1420 :
1421 3750 : M_dim = ncoset(order) - 1
1422 3750 : CPASSERT(M_dim <= SIZE(op, 1))
1423 :
1424 18750 : ALLOCATE (mab(ldab, ldab, M_dim))
1425 6053640 : mab(1:ldab, 1:ldab, 1:M_dim) = 0.0_dp
1426 22500 : ALLOCATE (difmab(ldab, ldab, M_dim, 3))
1427 18164670 : difmab(1:ldab, 1:ldab, 1:M_dim, 1:3) = 0.0_dp
1428 :
1429 15000 : ALLOCATE (work(ldwork, ldwork))
1430 672210 : work(1:ldwork, 1:ldwork) = 0.0_dp
1431 45000 : ALLOCATE (op_dip(M_dim))
1432 123750 : ALLOCATE (op_dip_der(M_dim, 3))
1433 :
1434 37500 : DO imom = 1, M_dim
1435 33750 : NULLIFY (op_dip(imom)%block)
1436 138750 : DO i = 1, 3
1437 135000 : NULLIFY (op_dip_der(imom, i)%block)
1438 : END DO
1439 : END DO
1440 :
1441 17388 : ALLOCATE (basis_set_list(nkind))
1442 9888 : DO ikind = 1, nkind
1443 6138 : qs_kind => qs_kind_set(ikind)
1444 6138 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
1445 9888 : IF (ASSOCIATED(basis_set_a)) THEN
1446 6138 : basis_set_list(ikind)%gto_basis_set => basis_set_a
1447 : ELSE
1448 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
1449 : END IF
1450 : END DO
1451 3750 : CALL neighbor_list_iterator_create(nl_iterator, sab_all)
1452 284943 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
1453 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
1454 281193 : iatom=iatom, jatom=jatom, r=rab)
1455 281193 : basis_set_a => basis_set_list(ikind)%gto_basis_set
1456 281193 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
1457 281193 : basis_set_b => basis_set_list(jkind)%gto_basis_set
1458 281193 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
1459 281193 : ra = pbc(particle_set(iatom)%r, cell)
1460 : ! basis ikind
1461 281193 : first_sgfa => basis_set_a%first_sgf
1462 281193 : la_max => basis_set_a%lmax
1463 281193 : la_min => basis_set_a%lmin
1464 281193 : npgfa => basis_set_a%npgf
1465 281193 : nseta = basis_set_a%nset
1466 281193 : nsgfa => basis_set_a%nsgf_set
1467 281193 : rpgfa => basis_set_a%pgf_radius
1468 281193 : set_radius_a => basis_set_a%set_radius
1469 281193 : sphi_a => basis_set_a%sphi
1470 281193 : zeta => basis_set_a%zet
1471 : ! basis jkind
1472 281193 : first_sgfb => basis_set_b%first_sgf
1473 281193 : lb_max => basis_set_b%lmax
1474 281193 : lb_min => basis_set_b%lmin
1475 281193 : npgfb => basis_set_b%npgf
1476 281193 : nsetb = basis_set_b%nset
1477 281193 : nsgfb => basis_set_b%nsgf_set
1478 281193 : rpgfb => basis_set_b%pgf_radius
1479 281193 : set_radius_b => basis_set_b%set_radius
1480 281193 : sphi_b => basis_set_b%sphi
1481 281193 : zetb => basis_set_b%zet
1482 :
1483 281193 : ldsa = SIZE(sphi_a, 1)
1484 281193 : IF (ldsa == 0) CYCLE
1485 281172 : ldsb = SIZE(sphi_b, 1)
1486 281172 : IF (ldsb == 0) CYCLE
1487 281172 : IF (inode == 1) last_jatom = 0
1488 :
1489 281172 : IF (my_minimum_image) THEN
1490 0 : IF (ABS(rab(1)) > Lxo2 .OR. ABS(rab(2)) > Lyo2 .OR. ABS(rab(3)) > Lzo2) CYCLE
1491 : END IF
1492 :
1493 1124688 : rb = rab + ra
1494 :
1495 281172 : IF (jatom /= last_jatom) THEN
1496 : new_atom_b = .TRUE.
1497 : last_jatom = jatom
1498 : ELSE
1499 : new_atom_b = .FALSE.
1500 : END IF
1501 :
1502 : IF (new_atom_b) THEN
1503 17958 : irow = iatom
1504 17958 : icol = jatom
1505 17958 : alpha_der = 2.0_dp
1506 :
1507 179580 : DO imom = 1, M_dim
1508 161622 : NULLIFY (op_dip(imom)%block)
1509 : CALL dbcsr_get_block_p(matrix=op(imom)%matrix, &
1510 : row=irow, col=icol, &
1511 : block=op_dip(imom)%block, &
1512 161622 : found=op_found)
1513 161622 : CPASSERT(op_found .AND. ASSOCIATED(op_dip(imom)%block))
1514 826068 : DO idir = 1, 3
1515 484866 : NULLIFY (op_dip_der(imom, idir)%block)
1516 : CALL dbcsr_get_block_p(matrix=op_der(imom, idir)%matrix, &
1517 : row=irow, col=icol, &
1518 : block=op_dip_der(imom, idir)%block, &
1519 484866 : found=op_der_found)
1520 646488 : CPASSERT(op_der_found .AND. ASSOCIATED(op_dip_der(imom, idir)%block))
1521 : END DO ! idir
1522 : END DO ! imom
1523 : END IF ! new_atom_b
1524 :
1525 281172 : rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
1526 281172 : dab = SQRT(rab2)
1527 :
1528 936090 : DO iset = 1, nseta
1529 :
1530 651168 : ncoa = npgfa(iset)*ncoset(la_max(iset))
1531 651168 : sgfa = first_sgfa(1, iset)
1532 :
1533 2511669 : DO jset = 1, nsetb
1534 :
1535 1579308 : ncob = npgfb(jset)*ncoset(lb_max(jset))
1536 1579308 : sgfb = first_sgfb(1, jset)
1537 :
1538 2230476 : IF (set_radius_a(iset) + set_radius_b(jset) >= dab) THEN
1539 :
1540 596982 : rac = pbc(rc, ra, cell)
1541 2387928 : rbc = rac + rab
1542 : ! rac = pbc(rc,ra,cell)
1543 : ! rbc = pbc(rc,rb,cell)
1544 :
1545 : ALLOCATE (mab_tmp(npgfa(iset)*ncoset(la_max(iset) + 1), &
1546 2958078 : npgfb(jset)*ncoset(lb_max(jset) + 1), ncoset(order) - 1))
1547 :
1548 596982 : lda_min = MAX(0, la_min(iset) - 1)
1549 596982 : ldb_min = MAX(0, lb_min(jset) - 1)
1550 : ! *** Calculate the primitive overlap integrals ***
1551 : CALL moment(la_max(iset) + 1, npgfa(iset), zeta(:, iset), &
1552 : rpgfa(:, iset), lda_min, &
1553 : lb_max(jset) + 1, npgfb(jset), zetb(:, jset), rpgfb(:, jset), &
1554 596982 : order, rac, rbc, mab_tmp)
1555 :
1556 : ! *** Calculate the derivatives
1557 : CALL diff_momop(la_max(iset), npgfa(iset), zeta(:, iset), &
1558 : rpgfa(:, iset), la_min(iset), lb_max(jset), npgfb(jset), &
1559 : zetb(:, jset), rpgfb(:, jset), lb_min(jset), order, rac, rbc, &
1560 596982 : difmab, mab_ext=mab_tmp)
1561 :
1562 : ! Contract and copy in the sparse matrix
1563 874316388 : mab = 0.0_dp
1564 5969820 : DO imom = 1, M_dim
1565 5372838 : na = 0
1566 5372838 : nda = 0
1567 17098830 : DO ipgf = 1, npgfa(iset)
1568 11725992 : nb = 0
1569 11725992 : ndb = 0
1570 42864039 : DO jpgf = 1, npgfb(jset)
1571 127844055 : DO j = 1, ncoset(lb_max(jset))
1572 486284148 : DO i = 1, ncoset(la_max(iset))
1573 455146101 : mab(i + na, j + nb, imom) = mab_tmp(i + nda, j + ndb, imom)
1574 : END DO ! i
1575 : END DO ! j
1576 31138047 : nb = nb + ncoset(lb_max(jset))
1577 42864039 : ndb = ndb + ncoset(lb_max(jset) + 1)
1578 : END DO ! jpgf
1579 11725992 : na = na + ncoset(la_max(iset))
1580 17098830 : nda = nda + ncoset(la_max(iset) + 1)
1581 : END DO ! ipgf
1582 :
1583 : ! *** Contraction ***
1584 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
1585 : 1.0_dp, mab(1, 1, imom), ldab, sphi_b(1, sgfb), ldsb, &
1586 5372838 : 0.0_dp, work(1, 1), ldwork)
1587 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
1588 : 1.0_dp, sphi_a(1, sgfa), ldsa, &
1589 : work(1, 1), ldwork, &
1590 : 1.0_dp, op_dip(imom)%block(sgfa, sgfb), &
1591 5372838 : SIZE(op_dip(imom)%block, 1))
1592 :
1593 5372838 : alpha = -1.0_dp !-alpha_der
1594 22088334 : DO idir = 1, 3
1595 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
1596 : alpha, difmab(1, 1, imom, idir), ldab, sphi_b(1, sgfb), ldsb, &
1597 16118514 : 0.0_dp, work(1, 1), ldwork)
1598 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
1599 : 1.0_dp, sphi_a(1, sgfa), ldsa, &
1600 : work(1, 1), ldwork, &
1601 : 1.0_dp, op_dip_der(imom, idir)%block(sgfa, sgfb), &
1602 21491352 : SIZE(op_dip_der(imom, idir)%block, 1))
1603 :
1604 : END DO ! idir
1605 :
1606 : END DO ! imom
1607 :
1608 596982 : DEALLOCATE (mab_tmp)
1609 : END IF ! >= dab
1610 :
1611 : END DO ! jset
1612 :
1613 : END DO ! iset
1614 :
1615 : END DO
1616 3750 : CALL neighbor_list_iterator_release(nl_iterator)
1617 :
1618 15000 : DO i = 1, 3
1619 15000 : NULLIFY (op_dip(i)%block)
1620 : END DO
1621 3750 : DEALLOCATE (op_dip, op_dip_der)
1622 :
1623 3750 : DEALLOCATE (mab, difmab, work, basis_set_list)
1624 :
1625 3750 : CALL timestop(handle)
1626 :
1627 7500 : END SUBROUTINE rRc_xyz_der_ao
1628 :
1629 : END MODULE qs_operators_ao
|