Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Calculate the first derivative of an integral block.
10 : !> \author Matthias Krack
11 : !> \date 05.10.2000
12 : !> \version 1.0
13 : !> \par Literature
14 : !> S. Obara and A. Saika, J. Chem. Phys. 84, 3963 (1986)
15 : !> \par Parameters
16 : !> - ax,ay,az : Angular momentum index numbers of orbital a.
17 : !> - bx,by,bz : Angular momentum index numbers of orbital b.
18 : !> - coset : Cartesian orbital set pointer.
19 : !> - l{a,b} : Angular momentum quantum number of shell a or b.
20 : !> - l{a,b}_max: Maximum angular momentum quantum number of shell a or b.
21 : !> - l{a,b}_min: Minimum angular momentum quantum number of shell a or b.
22 : !> - ncoset : Number of orbitals in a Cartesian orbital set.
23 : !> - npgf{a,b} : Degree of contraction of shell a or b.
24 : !> - rab : Distance vector between the atomic centers a and b.
25 : !> - rab2 : Square of the distance between the atomic centers a and b.
26 : !> - rac : Distance vector between the atomic centers a and c.
27 : !> - rac2 : Square of the distance between the atomic centers a and c.
28 : !> - rbc : Distance vector between the atomic centers b and c.
29 : !> - rbc2 : Square of the distance between the atomic centers b and c.
30 : !> - rpgf{a,b} : Radius of the primitive Gaussian-type function a or b.
31 : !> - zet{a,b} : Exponents of the Gaussian-type functions a or b.
32 : !> - zetp : Reciprocal of the sum of the exponents of orbital a and b.
33 : ! **************************************************************************************************
34 : MODULE ai_derivatives
35 :
36 : USE kinds, ONLY: dp
37 : USE orbital_pointers, ONLY: coset,&
38 : ncoset
39 : #include "../base/base_uses.f90"
40 :
41 : IMPLICIT NONE
42 :
43 : PRIVATE
44 :
45 : ! *** Public subroutines ***
46 : PUBLIC :: adbdr, dabdr, dabdr_noscreen
47 :
48 : CONTAINS
49 :
50 : ! **************************************************************************************************
51 : !> \brief Calculate the first derivative of an integral block.
52 : !> This takes the derivative with respect to
53 : !> the atomic position Ra, i.e. the center of the primitive on the left.
54 : !> To get the derivative of the left primitive with respect to r (orbital
55 : !> coordinate), take the opposite sign.
56 : !> To get the derivative with respect to the center of the primitive on
57 : !> the right Rb, take the opposite sign.
58 : !> To get the derivative of the right primitive with respect to r,
59 : !> do not change the sign.
60 : !> [da/dRi|O|b] = 2*zeta*[a+1i|O|b] - Ni(a)[a-1i|O|b]
61 : !>
62 : !> \param la_max ...
63 : !> \param npgfa ...
64 : !> \param zeta ...
65 : !> \param rpgfa ...
66 : !> \param la_min ...
67 : !> \param lb_max ...
68 : !> \param npgfb ...
69 : !> \param rpgfb ...
70 : !> \param lb_min ...
71 : !> \param dab ...
72 : !> \param ab ...
73 : !> \param dabdx ...
74 : !> \param dabdy ...
75 : !> \param dabdz ...
76 : !> \date 05.10.2000
77 : !> \author Matthias Krack
78 : !> \version 1.0
79 : ! **************************************************************************************************
80 37048 : SUBROUTINE dabdr(la_max, npgfa, zeta, rpgfa, la_min, lb_max, npgfb, rpgfb, lb_min, &
81 74096 : dab, ab, dabdx, dabdy, dabdz)
82 : INTEGER, INTENT(IN) :: la_max, npgfa
83 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: zeta, rpgfa
84 : INTEGER, INTENT(IN) :: la_min, lb_max, npgfb
85 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: rpgfb
86 : INTEGER, INTENT(IN) :: lb_min
87 : REAL(KIND=dp), INTENT(IN) :: dab
88 : REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: ab
89 : REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT) :: dabdx, dabdy, dabdz
90 :
91 : INTEGER :: ax, ay, az, bx, by, bz, coa, coamx, &
92 : coamy, coamz, coapx, coapy, coapz, &
93 : cob, codb, i, ipgf, j, jpgf, la, lb, &
94 : na, nb, nda, ndb
95 : REAL(KIND=dp) :: fa, fx, fy, fz
96 :
97 : ! *** Loop over all pairs of primitive Gaussian-type functions ***
98 :
99 37048 : na = 0
100 37048 : nda = 0
101 :
102 4821465 : dabdx = 0.0_dp
103 4821465 : dabdy = 0.0_dp
104 4821465 : dabdz = 0.0_dp
105 :
106 119038 : DO ipgf = 1, npgfa
107 :
108 81990 : fa = 2.0_dp*zeta(ipgf)
109 :
110 81990 : nb = 0
111 81990 : ndb = 0
112 :
113 298424 : DO jpgf = 1, npgfb
114 :
115 : ! *** Screening ***
116 :
117 216434 : IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) THEN
118 74385 : DO j = nb + ncoset(lb_min - 1) + 1, nb + ncoset(lb_max)
119 227152 : DO i = na + ncoset(la_min - 1) + 1, na + ncoset(la_max)
120 152767 : dabdx(i, j) = 0.0_dp
121 152767 : dabdy(i, j) = 0.0_dp
122 203150 : dabdz(i, j) = 0.0_dp
123 : END DO
124 : END DO
125 24002 : nb = nb + ncoset(lb_max)
126 24002 : ndb = ndb + ncoset(lb_max + 1)
127 24002 : CYCLE
128 : END IF
129 :
130 : ! *** [da/dRi|O|b] = 2*zeta*[a+1i|O|b] - Ni(a)[a-1i|O|b] ***
131 :
132 468233 : DO la = 0, la_max !MAX(0,la_min),la_max
133 :
134 468233 : IF (la == 0) THEN
135 :
136 192432 : coa = na + 1
137 192432 : coapx = nda + 2
138 192432 : coapy = nda + 3
139 192432 : coapz = nda + 4
140 :
141 467252 : DO lb = 0, lb_max !lb_min,lb_max
142 831447 : DO bx = 0, lb
143 1100186 : DO by = 0, lb - bx
144 461171 : bz = lb - bx - by
145 461171 : cob = nb + coset(bx, by, bz)
146 461171 : codb = ndb + coset(bx, by, bz)
147 461171 : dabdx(coa, cob) = fa*ab(coapx, codb)
148 461171 : dabdy(coa, cob) = fa*ab(coapy, codb)
149 825366 : dabdz(coa, cob) = fa*ab(coapz, codb)
150 : END DO
151 : END DO
152 : END DO
153 :
154 : ELSE
155 :
156 257268 : DO ax = 0, la
157 529472 : DO ay = 0, la - ax
158 272204 : az = la - ax - ay
159 :
160 272204 : coa = na + coset(ax, ay, az)
161 272204 : coamx = nda + coset(MAX(0, ax - 1), ay, az)
162 272204 : coamy = nda + coset(ax, MAX(0, ay - 1), az)
163 272204 : coamz = nda + coset(ax, ay, MAX(0, az - 1))
164 272204 : coapx = nda + coset(ax + 1, ay, az)
165 272204 : coapy = nda + coset(ax, ay + 1, az)
166 272204 : coapz = nda + coset(ax, ay, az + 1)
167 :
168 272204 : fx = REAL(ax, dp)
169 272204 : fy = REAL(ay, dp)
170 272204 : fz = REAL(az, dp)
171 :
172 866575 : DO lb = 0, lb_max !lb_min,lb_max
173 1282229 : DO bx = 0, lb
174 1791890 : DO by = 0, lb - bx
175 781865 : bz = lb - bx - by
176 781865 : cob = nb + coset(bx, by, bz)
177 781865 : codb = ndb + coset(bx, by, bz)
178 781865 : dabdx(coa, cob) = fa*ab(coapx, codb) - fx*ab(coamx, codb)
179 781865 : dabdy(coa, cob) = fa*ab(coapy, codb) - fy*ab(coamy, codb)
180 1371418 : dabdz(coa, cob) = fa*ab(coapz, codb) - fz*ab(coamz, codb)
181 : END DO
182 : END DO
183 : END DO
184 :
185 : END DO
186 : END DO
187 :
188 : END IF
189 :
190 : END DO
191 :
192 192432 : nb = nb + ncoset(lb_max)
193 274422 : ndb = ndb + ncoset(lb_max + 1)
194 :
195 : END DO
196 :
197 81990 : na = na + ncoset(la_max)
198 119038 : nda = nda + ncoset(la_max + 1)
199 :
200 : END DO
201 :
202 37048 : END SUBROUTINE dabdr
203 :
204 : ! **************************************************************************************************
205 : !> \brief Calculate the first derivative of an integral block.
206 : !> This takes the derivative with respect to
207 : !> the atomic position Rb, i.e. the center of the primitive on the right.
208 : !> To get the derivative of the left primitive with respect to r
209 : !> (orbital coordinate), take the opposite sign.
210 : !> [a|O|db/dRi] = 2*zetb*[a|O|b+1i] - Ni(b)[a|O|b-1i]
211 : !> \param la_max ...
212 : !> \param npgfa ...
213 : !> \param rpgfa ...
214 : !> \param la_min ...
215 : !> \param lb_max ...
216 : !> \param npgfb ...
217 : !> \param zetb ...
218 : !> \param rpgfb ...
219 : !> \param lb_min ...
220 : !> \param dab ...
221 : !> \param ab ...
222 : !> \param adbdx ...
223 : !> \param adbdy ...
224 : !> \param adbdz ...
225 : !> \date 05.10.2000
226 : !> \author Matthias Krack
227 : !> \version 1.0
228 : ! **************************************************************************************************
229 5387623 : SUBROUTINE adbdr(la_max, npgfa, rpgfa, la_min, lb_max, npgfb, zetb, rpgfb, lb_min, &
230 10775246 : dab, ab, adbdx, adbdy, adbdz)
231 : INTEGER, INTENT(IN) :: la_max, npgfa
232 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: rpgfa
233 : INTEGER, INTENT(IN) :: la_min, lb_max, npgfb
234 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: zetb, rpgfb
235 : INTEGER, INTENT(IN) :: lb_min
236 : REAL(KIND=dp), INTENT(IN) :: dab
237 : REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: ab
238 : REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT) :: adbdx, adbdy, adbdz
239 :
240 : INTEGER :: ax, ay, az, bx, by, bz, coa, cob, cobmx, &
241 : cobmy, cobmz, cobpx, cobpy, cobpz, &
242 : coda, i, ipgf, j, jpgf, la, lb, na, &
243 : nb, nda, ndb
244 : REAL(KIND=dp) :: fb, fx, fy, fz
245 :
246 5387623 : na = 0
247 5387623 : nda = 0
248 :
249 401019996 : adbdx = 0.0_dp
250 401019996 : adbdy = 0.0_dp
251 401019996 : adbdz = 0.0_dp
252 : ! *** Loop over all pairs of primitive Gaussian-type functions ***
253 17160776 : DO ipgf = 1, npgfa
254 :
255 11773153 : nb = 0
256 11773153 : ndb = 0
257 :
258 43075028 : DO jpgf = 1, npgfb
259 :
260 31301875 : fb = 2.0_dp*zetb(jpgf)
261 :
262 : ! *** Screening ***
263 :
264 31301875 : IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) THEN
265 81029109 : DO j = nb + ncoset(lb_min - 1) + 1, nb + ncoset(lb_max)
266 284437479 : DO i = na + ncoset(la_min - 1) + 1, na + ncoset(la_max)
267 203408370 : adbdx(i, j) = 0.0_dp
268 203408370 : adbdy(i, j) = 0.0_dp
269 263302257 : adbdz(i, j) = 0.0_dp
270 : END DO
271 : END DO
272 21135222 : nb = nb + ncoset(lb_max)
273 21135222 : ndb = ndb + ncoset(lb_max + 1)
274 21135222 : CYCLE
275 : END IF
276 :
277 : ! *** [a|O|db/dRi] = 2*zetb*[a|O|b+1i] - Ni(b)[a|O|b-1i] ***
278 :
279 27059488 : DO lb = 0, lb_max
280 :
281 27059488 : IF (lb == 0) THEN
282 :
283 10166653 : cob = nb + 1
284 10166653 : cobpx = ndb + 2
285 10166653 : cobpy = ndb + 3
286 10166653 : cobpz = ndb + 4
287 :
288 27060550 : DO la = 0, la_max !la_min,la_max
289 51419106 : DO ax = 0, la
290 73813083 : DO ay = 0, la - ax
291 32560630 : az = la - ax - ay
292 32560630 : coa = na + coset(ax, ay, az)
293 32560630 : coda = nda + coset(ax, ay, az)
294 32560630 : adbdx(coa, cob) = fb*ab(coda, cobpx)
295 32560630 : adbdy(coa, cob) = fb*ab(coda, cobpy)
296 56919186 : adbdz(coa, cob) = fb*ab(coda, cobpz)
297 : END DO
298 : END DO
299 : END DO
300 : ELSE
301 :
302 20915799 : DO bx = 0, lb
303 43306104 : DO by = 0, lb - bx
304 22390305 : bz = lb - bx - by
305 :
306 22390305 : cob = nb + coset(bx, by, bz)
307 22390305 : cobmx = ndb + coset(MAX(0, bx - 1), by, bz)
308 22390305 : cobmy = ndb + coset(bx, MAX(0, by - 1), bz)
309 22390305 : cobmz = ndb + coset(bx, by, MAX(0, bz - 1))
310 22390305 : cobpx = ndb + coset(bx + 1, by, bz)
311 22390305 : cobpy = ndb + coset(bx, by + 1, bz)
312 22390305 : cobpz = ndb + coset(bx, by, bz + 1)
313 :
314 22390305 : fx = REAL(bx, dp)
315 22390305 : fy = REAL(by, dp)
316 22390305 : fz = REAL(bz, dp)
317 :
318 79704094 : DO la = 0, la_max !la_min,la_max
319 131689599 : DO ax = 0, la
320 200842449 : DO ay = 0, la - ax
321 91543155 : az = la - ax - ay
322 91543155 : coa = na + coset(ax, ay, az)
323 91543155 : coda = nda + coset(ax, ay, az)
324 91543155 : adbdx(coa, cob) = fb*ab(coda, cobpx) - fx*ab(coda, cobmx)
325 91543155 : adbdy(coa, cob) = fb*ab(coda, cobpy) - fy*ab(coda, cobmy)
326 157718277 : adbdz(coa, cob) = fb*ab(coda, cobpz) - fz*ab(coda, cobmz)
327 : END DO
328 : END DO
329 : END DO
330 :
331 : END DO
332 : END DO
333 :
334 : END IF
335 :
336 : END DO
337 :
338 10166653 : nb = nb + ncoset(lb_max)
339 21939806 : ndb = ndb + ncoset(lb_max + 1)
340 :
341 : END DO
342 :
343 11773153 : na = na + ncoset(la_max)
344 17160776 : nda = nda + ncoset(la_max + 1)
345 :
346 : END DO
347 :
348 5387623 : END SUBROUTINE adbdr
349 : ! **************************************************************************************************
350 : !> \brief Calculate the first derivative of an integral block.
351 : !> This takes the derivative with respect to
352 : !> the atomic position Ra, i.e. the center of the primitive on the left.
353 : !> Difference to routine dabdr: employs no (!!) screening, which is relevant when
354 : !> calculating the derivatives of Coulomb integrals
355 : !> \param la_max ...
356 : !> \param npgfa ...
357 : !> \param zeta ...
358 : !> \param lb_max ...
359 : !> \param npgfb ...
360 : !> \param ab ...
361 : !> \param dabdx ...
362 : !> \param dabdy ...
363 : !> \param dabdz ...
364 : ! **************************************************************************************************
365 24000 : SUBROUTINE dabdr_noscreen(la_max, npgfa, zeta, lb_max, npgfb, ab, dabdx, dabdy, dabdz)
366 : INTEGER, INTENT(IN) :: la_max, npgfa
367 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: zeta
368 : INTEGER, INTENT(IN) :: lb_max, npgfb
369 : REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: ab
370 : REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT) :: dabdx, dabdy, dabdz
371 :
372 : INTEGER :: ax, ay, az, bx, by, bz, coa, coamx, &
373 : coamy, coamz, coapx, coapy, coapz, &
374 : cob, codb, ipgf, jpgf, la, lb, na, nb, &
375 : nda, ndb
376 : REAL(KIND=dp) :: fa, fx, fy, fz
377 :
378 : ! *** Loop over all pairs of primitive Gaussian-type functions ***
379 :
380 24000 : na = 0
381 24000 : nda = 0
382 :
383 8456000 : dabdx = 0.0_dp
384 8456000 : dabdy = 0.0_dp
385 8456000 : dabdz = 0.0_dp
386 :
387 48000 : DO ipgf = 1, npgfa
388 :
389 24000 : fa = 2.0_dp*zeta(ipgf)
390 :
391 24000 : nb = 0
392 24000 : ndb = 0
393 :
394 48000 : DO jpgf = 1, npgfb
395 :
396 : !*** [da/dRi|O|b] = 2*zeta*[a+1i|O|b] - Ni(a)[a-1i|O|b] ***
397 :
398 103200 : DO la = 0, la_max !MAX(0,la_min),la_max
399 :
400 103200 : IF (la == 0) THEN
401 :
402 24000 : coa = na + 1
403 24000 : coapx = nda + 2
404 24000 : coapy = nda + 3
405 24000 : coapz = nda + 4
406 :
407 115200 : DO lb = 0, lb_max !lb_min,lb_max
408 361600 : DO bx = 0, lb
409 881600 : DO by = 0, lb - bx
410 544000 : bz = lb - bx - by
411 544000 : cob = nb + coset(bx, by, bz)
412 544000 : codb = ndb + coset(bx, by, bz)
413 544000 : dabdx(coa, cob) = fa*ab(coapx, codb)
414 544000 : dabdy(coa, cob) = fa*ab(coapy, codb)
415 790400 : dabdz(coa, cob) = fa*ab(coapz, codb)
416 : END DO
417 : END DO
418 : END DO
419 :
420 : ELSE
421 :
422 213600 : DO ax = 0, la
423 537600 : DO ay = 0, la - ax
424 324000 : az = la - ax - ay
425 :
426 324000 : coa = na + coset(ax, ay, az)
427 324000 : coamx = nda + coset(MAX(0, ax - 1), ay, az)
428 324000 : coamy = nda + coset(ax, MAX(0, ay - 1), az)
429 324000 : coamz = nda + coset(ax, ay, MAX(0, az - 1))
430 324000 : coapx = nda + coset(ax + 1, ay, az)
431 324000 : coapy = nda + coset(ax, ay + 1, az)
432 324000 : coapz = nda + coset(ax, ay, az + 1)
433 :
434 324000 : fx = REAL(ax, dp)
435 324000 : fy = REAL(ay, dp)
436 324000 : fz = REAL(az, dp)
437 :
438 1713600 : DO lb = 0, lb_max !lb_min,lb_max
439 4881600 : DO bx = 0, lb
440 11901600 : DO by = 0, lb - bx
441 7344000 : bz = lb - bx - by
442 7344000 : cob = nb + coset(bx, by, bz)
443 7344000 : codb = ndb + coset(bx, by, bz)
444 7344000 : dabdx(coa, cob) = fa*ab(coapx, codb) - fx*ab(coamx, codb)
445 7344000 : dabdy(coa, cob) = fa*ab(coapy, codb) - fy*ab(coamy, codb)
446 10670400 : dabdz(coa, cob) = fa*ab(coapz, codb) - fz*ab(coamz, codb)
447 : END DO
448 : END DO
449 : END DO
450 :
451 : END DO
452 : END DO
453 :
454 : END IF
455 :
456 : END DO
457 :
458 24000 : nb = nb + ncoset(lb_max)
459 48000 : ndb = ndb + ncoset(lb_max + 1)
460 :
461 : END DO
462 :
463 24000 : na = na + ncoset(la_max)
464 48000 : nda = nda + ncoset(la_max + 1)
465 :
466 : END DO
467 :
468 24000 : END SUBROUTINE dabdr_noscreen
469 :
470 : END MODULE ai_derivatives
471 :
|