(git:374b731)
Loading...
Searching...
No Matches
qs_o3c_methods.F
Go to the documentation of this file.
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!> \brief Methods used with 3-center overlap type integrals containers
9!> \par History
10!> - none
11!> - 11.2018 fixed OMP race condition in contract3_o3c routine (A.Bussy)
12! **************************************************************************************************
15 USE ai_overlap3, ONLY: overlap3
18 USE dbcsr_api, ONLY: dbcsr_get_block_p,&
19 dbcsr_p_type,&
20 dbcsr_type
21 USE kinds, ONLY: dp
22 USE orbital_pointers, ONLY: ncoset
23 USE qs_o3c_types, ONLY: &
27
28!$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num
29#include "./base/base_uses.f90"
30
31 IMPLICIT NONE
32
33 PRIVATE
34
35 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_o3c_methods'
36
38
39CONTAINS
40
41! **************************************************************************************************
42!> \brief ...
43!> \param o3c ...
44!> \param calculate_forces ...
45!> \param matrix_p ...
46! **************************************************************************************************
47 SUBROUTINE calculate_o3c_integrals(o3c, calculate_forces, matrix_p)
48 TYPE(o3c_container_type), POINTER :: o3c
49 LOGICAL, INTENT(IN), OPTIONAL :: calculate_forces
50 TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
51 POINTER :: matrix_p
52
53 CHARACTER(LEN=*), PARAMETER :: routinen = 'calculate_o3c_integrals'
54
55 INTEGER :: egfa, egfb, egfc, handle, i, iatom, icol, ikind, irow, iset, ispin, j, jatom, &
56 jkind, jset, katom, kkind, kset, mepos, ncoa, ncob, ncoc, ni, nj, nk, nseta, nsetb, &
57 nsetc, nspin, nthread, sgfa, sgfb, sgfc
58 INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, lc_max, &
59 lc_min, npgfa, npgfb, npgfc, nsgfa, &
60 nsgfb, nsgfc
61 INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb, first_sgfc
62 LOGICAL :: do_force, found, trans
63 REAL(kind=dp) :: dij, dik, djk, fpre
64 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: pmat
65 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: sabc, sabc_contr
66 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: iabdc, iadbc, idabc, sabdc, sdabc
67 REAL(kind=dp), DIMENSION(3) :: rij, rik, rjk
68 REAL(kind=dp), DIMENSION(:), POINTER :: set_radius_a, set_radius_b, set_radius_c
69 REAL(kind=dp), DIMENSION(:, :), POINTER :: fi, fj, fk, pblock, rpgfa, rpgfb, rpgfc, &
70 sphi_a, sphi_b, sphi_c, tvec, zeta, &
71 zetb, zetc
72 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: iabc
73 TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list_a, basis_set_list_b, &
74 basis_set_list_c
75 TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b, basis_set_c
76 TYPE(o3c_iterator_type) :: o3c_iterator
77
78 CALL timeset(routinen, handle)
79
80 do_force = .false.
81 IF (PRESENT(calculate_forces)) do_force = calculate_forces
82 CALL get_o3c_container(o3c, nspin=nspin)
83
84 ! basis sets
85 CALL get_o3c_container(o3c, basis_set_list_a=basis_set_list_a, &
86 basis_set_list_b=basis_set_list_b, basis_set_list_c=basis_set_list_c)
87
88 nthread = 1
89!$ nthread = omp_get_max_threads()
90 CALL o3c_iterator_create(o3c, o3c_iterator, nthread=nthread)
91
92!$OMP PARALLEL DEFAULT(NONE) &
93!$OMP SHARED (nthread,o3c_iterator,ncoset,nspin,basis_set_list_a,basis_set_list_b,&
94!$OMP basis_set_list_c,do_force,matrix_p)&
95!$OMP PRIVATE (mepos,ikind,jkind,kkind,basis_set_a,basis_set_b,basis_set_c,rij,rik,rjk,&
96!$OMP first_sgfa,la_max,la_min,npgfa,nseta,nsgfa,rpgfa,set_radius_a,sphi_a,zeta,&
97!$OMP first_sgfb,lb_max,lb_min,npgfb,nsetb,nsgfb,rpgfb,set_radius_b,sphi_b,zetb,&
98!$OMP first_sgfc,lc_max,lc_min,npgfc,nsetc,nsgfc,rpgfc,set_radius_c,sphi_c,zetc,&
99!$OMP iset,jset,kset,dij,dik,djk,ni,nj,nk,iabc,idabc,iadbc,iabdc,tvec,fi,fj,fk,ncoa,&
100!$OMP ncob,ncoc,sabc,sabc_contr,sdabc,sabdc,sgfa,sgfb,sgfc,egfa,egfb,egfc,i,j,&
101!$OMP pblock,pmat,ispin,iatom,jatom,katom,irow,icol,found,trans,fpre)
102
103 mepos = 0
104!$ mepos = omp_get_thread_num()
105
106 DO WHILE (o3c_iterate(o3c_iterator, mepos=mepos) == 0)
107 CALL get_o3c_iterator_info(o3c_iterator, mepos=mepos, &
108 ikind=ikind, jkind=jkind, kkind=kkind, rij=rij, rik=rik, &
109 integral=iabc, tvec=tvec, force_i=fi, force_j=fj, force_k=fk)
110 cpassert(.NOT. ASSOCIATED(iabc))
111 cpassert(.NOT. ASSOCIATED(tvec))
112 cpassert(.NOT. ASSOCIATED(fi))
113 cpassert(.NOT. ASSOCIATED(fj))
114 cpassert(.NOT. ASSOCIATED(fk))
115 ! basis
116 basis_set_a => basis_set_list_a(ikind)%gto_basis_set
117 basis_set_b => basis_set_list_b(jkind)%gto_basis_set
118 basis_set_c => basis_set_list_c(kkind)%gto_basis_set
119 ! center A
120 first_sgfa => basis_set_a%first_sgf
121 la_max => basis_set_a%lmax
122 la_min => basis_set_a%lmin
123 npgfa => basis_set_a%npgf
124 nseta = basis_set_a%nset
125 nsgfa => basis_set_a%nsgf_set
126 rpgfa => basis_set_a%pgf_radius
127 set_radius_a => basis_set_a%set_radius
128 sphi_a => basis_set_a%sphi
129 zeta => basis_set_a%zet
130 ! center B
131 first_sgfb => basis_set_b%first_sgf
132 lb_max => basis_set_b%lmax
133 lb_min => basis_set_b%lmin
134 npgfb => basis_set_b%npgf
135 nsetb = basis_set_b%nset
136 nsgfb => basis_set_b%nsgf_set
137 rpgfb => basis_set_b%pgf_radius
138 set_radius_b => basis_set_b%set_radius
139 sphi_b => basis_set_b%sphi
140 zetb => basis_set_b%zet
141 ! center C (RI)
142 first_sgfc => basis_set_c%first_sgf
143 lc_max => basis_set_c%lmax
144 lc_min => basis_set_c%lmin
145 npgfc => basis_set_c%npgf
146 nsetc = basis_set_c%nset
147 nsgfc => basis_set_c%nsgf_set
148 rpgfc => basis_set_c%pgf_radius
149 set_radius_c => basis_set_c%set_radius
150 sphi_c => basis_set_c%sphi
151 zetc => basis_set_c%zet
152
153 ni = sum(nsgfa)
154 nj = sum(nsgfb)
155 nk = sum(nsgfc)
156
157 ALLOCATE (iabc(ni, nj, nk))
158 iabc(:, :, :) = 0.0_dp
159 IF (do_force) THEN
160 ALLOCATE (fi(nk, 3), fj(nk, 3), fk(nk, 3))
161 fi(:, :) = 0.0_dp
162 fj(:, :) = 0.0_dp
163 fk(:, :) = 0.0_dp
164 ALLOCATE (idabc(ni, nj, nk, 3))
165 idabc(:, :, :, :) = 0.0_dp
166 ALLOCATE (iadbc(ni, nj, nk, 3))
167 iadbc(:, :, :, :) = 0.0_dp
168 ALLOCATE (iabdc(ni, nj, nk, 3))
169 iabdc(:, :, :, :) = 0.0_dp
170 ELSE
171 NULLIFY (fi, fj, fk)
172 END IF
173 ALLOCATE (tvec(nk, nspin))
174 tvec(:, :) = 0.0_dp
175
176 rjk(1:3) = rik(1:3) - rij(1:3)
177 dij = norm2(rij)
178 dik = norm2(rik)
179 djk = norm2(rjk)
180
181 DO iset = 1, nseta
182 DO jset = 1, nsetb
183 IF (set_radius_a(iset) + set_radius_b(jset) < dij) cycle
184 DO kset = 1, nsetc
185 IF (set_radius_a(iset) + set_radius_c(kset) < dik) cycle
186 IF (set_radius_b(jset) + set_radius_c(kset) < djk) cycle
187
188 ncoa = npgfa(iset)*ncoset(la_max(iset))
189 ncob = npgfb(jset)*ncoset(lb_max(jset))
190 ncoc = npgfc(kset)*ncoset(lc_max(kset))
191
192 sgfa = first_sgfa(1, iset)
193 sgfb = first_sgfb(1, jset)
194 sgfc = first_sgfc(1, kset)
195
196 egfa = sgfa + nsgfa(iset) - 1
197 egfb = sgfb + nsgfb(jset) - 1
198 egfc = sgfc + nsgfc(kset) - 1
199
200 IF (ncoa*ncob*ncoc > 0) THEN
201 ALLOCATE (sabc(ncoa, ncob, ncoc))
202 sabc(:, :, :) = 0.0_dp
203 IF (do_force) THEN
204 ALLOCATE (sdabc(ncoa, ncob, ncoc, 3))
205 sdabc(:, :, :, :) = 0.0_dp
206 ALLOCATE (sabdc(ncoa, ncob, ncoc, 3))
207 sabdc(:, :, :, :) = 0.0_dp
208 CALL overlap3(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
209 lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), lb_min(jset), &
210 lc_max(kset), npgfc(kset), zetc(:, kset), rpgfc(:, kset), lc_min(kset), &
211 rij, dij, rik, dik, rjk, djk, sabc, sdabc, sabdc)
212 ELSE
213 CALL overlap3(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
214 lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), lb_min(jset), &
215 lc_max(kset), npgfc(kset), zetc(:, kset), rpgfc(:, kset), lc_min(kset), &
216 rij, dij, rik, dik, rjk, djk, sabc)
217 END IF
218 ALLOCATE (sabc_contr(nsgfa(iset), nsgfb(jset), nsgfc(kset)))
219
220 CALL abc_contract(sabc_contr, sabc, &
221 sphi_a(:, sgfa:), sphi_b(:, sgfb:), sphi_c(:, sgfc:), &
222 ncoa, ncob, ncoc, nsgfa(iset), nsgfb(jset), nsgfc(kset))
223 iabc(sgfa:egfa, sgfb:egfb, sgfc:egfc) = &
224 sabc_contr(1:nsgfa(iset), 1:nsgfb(jset), 1:nsgfc(kset))
225 IF (do_force) THEN
226 DO i = 1, 3
227 CALL abc_contract(sabc_contr, sdabc(:, :, :, i), &
228 sphi_a(:, sgfa:), sphi_b(:, sgfb:), sphi_c(:, sgfc:), &
229 ncoa, ncob, ncoc, nsgfa(iset), nsgfb(jset), nsgfc(kset))
230 idabc(sgfa:egfa, sgfb:egfb, sgfc:egfc, i) = &
231 sabc_contr(1:nsgfa(iset), 1:nsgfb(jset), 1:nsgfc(kset))
232 CALL abc_contract(sabc_contr, sabdc(:, :, :, i), &
233 sphi_a(:, sgfa:), sphi_b(:, sgfb:), sphi_c(:, sgfc:), &
234 ncoa, ncob, ncoc, nsgfa(iset), nsgfb(jset), nsgfc(kset))
235 iabdc(sgfa:egfa, sgfb:egfb, sgfc:egfc, i) = &
236 sabc_contr(1:nsgfa(iset), 1:nsgfb(jset), 1:nsgfc(kset))
237 END DO
238 END IF
239
240 DEALLOCATE (sabc_contr)
241 DEALLOCATE (sabc)
242 END IF
243 IF (do_force) THEN
244 DEALLOCATE (sdabc, sabdc)
245 END IF
246 END DO
247 END DO
248 END DO
249 IF (do_force) THEN
250 ! translational invariance
251 iadbc(:, :, :, :) = -idabc(:, :, :, :) - iabdc(:, :, :, :)
252 !
253 ! get the atom indices
254 CALL get_o3c_iterator_info(o3c_iterator, mepos=mepos, &
255 iatom=iatom, jatom=jatom, katom=katom)
256 !
257 ! contract over i and j to get forces
258 IF (iatom <= jatom) THEN
259 irow = iatom
260 icol = jatom
261 trans = .false.
262 ELSE
263 irow = jatom
264 icol = iatom
265 trans = .true.
266 END IF
267 IF (iatom == jatom) THEN
268 fpre = 1.0_dp
269 ELSE
270 fpre = 2.0_dp
271 END IF
272 ALLOCATE (pmat(ni, nj))
273 pmat(:, :) = 0.0_dp
274 DO ispin = 1, nspin
275 CALL dbcsr_get_block_p(matrix=matrix_p(ispin)%matrix, &
276 row=irow, col=icol, block=pblock, found=found)
277 IF (found) THEN
278 IF (trans) THEN
279 pmat(:, :) = pmat(:, :) + transpose(pblock(:, :))
280 ELSE
281 pmat(:, :) = pmat(:, :) + pblock(:, :)
282 END IF
283 END IF
284 END DO
285 DO i = 1, 3
286 DO j = 1, nk
287 fi(j, i) = fpre*sum(pmat(:, :)*idabc(:, :, j, i))
288 fj(j, i) = fpre*sum(pmat(:, :)*iadbc(:, :, j, i))
289 fk(j, i) = fpre*sum(pmat(:, :)*iabdc(:, :, j, i))
290 END DO
291 END DO
292 DEALLOCATE (pmat)
293 !
294 DEALLOCATE (idabc, iadbc, iabdc)
295 END IF
296 !
297 CALL set_o3c_container(o3c_iterator, mepos=mepos, &
298 integral=iabc, tvec=tvec, force_i=fi, force_j=fj, force_k=fk)
299
300 END DO
301!$OMP END PARALLEL
302 CALL o3c_iterator_release(o3c_iterator)
303
304 CALL timestop(handle)
305
306 END SUBROUTINE calculate_o3c_integrals
307
308! **************************************************************************************************
309!> \brief Contraction of 3-tensor over indices 1 and 2 (assuming symmetry)
310!> t(k) = sum_ij (ijk)*p(ij)
311!> \param o3c ...
312!> \param matrix_p ...
313! **************************************************************************************************
314 SUBROUTINE contract12_o3c(o3c, matrix_p)
315 TYPE(o3c_container_type), POINTER :: o3c
316 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_p
317
318 CHARACTER(LEN=*), PARAMETER :: routinen = 'contract12_o3c'
319
320 INTEGER :: handle, iatom, icol, ik, irow, ispin, &
321 jatom, mepos, nk, nspin, nthread
322 LOGICAL :: found, ijsymmetric, trans
323 REAL(kind=dp) :: fpre
324 REAL(kind=dp), DIMENSION(:, :), POINTER :: pblock, tvec
325 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: iabc
326 TYPE(o3c_iterator_type) :: o3c_iterator
327
328 CALL timeset(routinen, handle)
329
330 nspin = SIZE(matrix_p, 1)
331 CALL get_o3c_container(o3c, ijsymmetric=ijsymmetric)
332 cpassert(ijsymmetric)
333
334 nthread = 1
335!$ nthread = omp_get_max_threads()
336 CALL o3c_iterator_create(o3c, o3c_iterator, nthread=nthread)
337
338!$OMP PARALLEL DEFAULT(NONE) &
339!$OMP SHARED (nthread,o3c_iterator,matrix_p,nspin)&
340!$OMP PRIVATE (mepos,ispin,iatom,jatom,ik,nk,irow,icol,iabc,tvec,found,pblock,trans,fpre)
341
342 mepos = 0
343!$ mepos = omp_get_thread_num()
344
345 DO WHILE (o3c_iterate(o3c_iterator, mepos=mepos) == 0)
346 CALL get_o3c_iterator_info(o3c_iterator, mepos=mepos, iatom=iatom, jatom=jatom, &
347 integral=iabc, tvec=tvec)
348 nk = SIZE(tvec, 1)
349
350 IF (iatom <= jatom) THEN
351 irow = iatom
352 icol = jatom
353 trans = .false.
354 ELSE
355 irow = jatom
356 icol = iatom
357 trans = .true.
358 END IF
359 IF (iatom == jatom) THEN
360 fpre = 1.0_dp
361 ELSE
362 fpre = 2.0_dp
363 END IF
364
365 DO ispin = 1, nspin
366 CALL dbcsr_get_block_p(matrix=matrix_p(ispin)%matrix, &
367 row=irow, col=icol, block=pblock, found=found)
368 IF (found) THEN
369 IF (trans) THEN
370 DO ik = 1, nk
371 tvec(ik, ispin) = fpre*sum(transpose(pblock(:, :))*iabc(:, :, ik))
372 END DO
373 ELSE
374 DO ik = 1, nk
375 tvec(ik, ispin) = fpre*sum(pblock(:, :)*iabc(:, :, ik))
376 END DO
377 END IF
378 END IF
379 END DO
380
381 END DO
382!$OMP END PARALLEL
383 CALL o3c_iterator_release(o3c_iterator)
384
385 CALL timestop(handle)
386
387 END SUBROUTINE contract12_o3c
388
389! **************************************************************************************************
390!> \brief Contraction of 3-tensor over index 3
391!> h(ij) = h(ij) + sum_k (ijk)*v(k)
392!> \param o3c ...
393!> \param vec ...
394!> \param matrix ...
395! **************************************************************************************************
396 SUBROUTINE contract3_o3c(o3c, vec, matrix)
397 TYPE(o3c_container_type), POINTER :: o3c
398 TYPE(o3c_vec_type), DIMENSION(:), POINTER :: vec
399 TYPE(dbcsr_type) :: matrix
400
401 CHARACTER(LEN=*), PARAMETER :: routinen = 'contract3_o3c'
402
403 INTEGER :: handle, iatom, icol, ik, irow, jatom, &
404 katom, mepos, nk, nthread, s1, s2
405 LOGICAL :: found, ijsymmetric, trans
406 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: work
407 REAL(kind=dp), DIMENSION(:), POINTER :: v
408 REAL(kind=dp), DIMENSION(:, :), POINTER :: pblock
409 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: iabc
410 TYPE(o3c_iterator_type) :: o3c_iterator
411
412 CALL timeset(routinen, handle)
413
414 CALL get_o3c_container(o3c, ijsymmetric=ijsymmetric)
415 cpassert(ijsymmetric)
416
417 nthread = 1
418!$ nthread = omp_get_max_threads()
419 CALL o3c_iterator_create(o3c, o3c_iterator, nthread=nthread)
420
421!$OMP PARALLEL DEFAULT(NONE) &
422!$OMP SHARED (nthread,o3c_iterator,vec,matrix)&
423!$OMP PRIVATE (mepos,iabc,iatom,jatom,katom,irow,icol,trans,pblock,v,found,ik,nk,work,s1,s2)
424
425 mepos = 0
426!$ mepos = omp_get_thread_num()
427
428 DO WHILE (o3c_iterate(o3c_iterator, mepos=mepos) == 0)
429 CALL get_o3c_iterator_info(o3c_iterator, mepos=mepos, iatom=iatom, jatom=jatom, katom=katom, &
430 integral=iabc)
431
432 CALL get_o3c_vec(vec, katom, v)
433 nk = SIZE(v)
434
435 IF (iatom <= jatom) THEN
436 irow = iatom
437 icol = jatom
438 trans = .false.
439 ELSE
440 irow = jatom
441 icol = iatom
442 trans = .true.
443 END IF
444
445 CALL dbcsr_get_block_p(matrix=matrix, row=irow, col=icol, block=pblock, found=found)
446
447 IF (found) THEN
448 s1 = SIZE(pblock, 1); s2 = SIZE(pblock, 2)
449 ALLOCATE (work(s1, s2))
450 work(:, :) = 0.0_dp
451
452 IF (trans) THEN
453 DO ik = 1, nk
454 CALL daxpy(s1*s2, v(ik), transpose(iabc(:, :, ik)), 1, work(:, :), 1)
455 END DO
456 ELSE
457 DO ik = 1, nk
458 CALL daxpy(s1*s2, v(ik), iabc(:, :, ik), 1, work(:, :), 1)
459 END DO
460 END IF
461
462 ! Multiple threads with same irow, icol but different katom (same even in PBCs) can try
463 ! to access the dbcsr block at the same time. Prevent that by CRITICAL section but keep
464 ! computations before hand in order to retain speed
465
466!$OMP CRITICAL
467 CALL dbcsr_get_block_p(matrix=matrix, row=irow, col=icol, block=pblock, found=found)
468 CALL daxpy(s1*s2, 1.0_dp, work(:, :), 1, pblock(:, :), 1)
469!$OMP END CRITICAL
470
471 DEALLOCATE (work)
472 END IF
473
474 END DO
475!$OMP END PARALLEL
476 CALL o3c_iterator_release(o3c_iterator)
477
478 CALL timestop(handle)
479
480 END SUBROUTINE contract3_o3c
481
482END MODULE qs_o3c_methods
Contraction of integrals over primitive Cartesian Gaussians based on the contraction matrix sphi whic...
subroutine, public abc_contract(abcint, sabc, sphi_a, sphi_b, sphi_c, ncoa, ncob, ncoc, nsgfa, nsgfb, nsgfc)
contract three-center overlap integrals (a,b,c) and transfer to spherical Gaussians
subroutine, public overlap3(la_max_set, npgfa, zeta, rpgfa, la_min_set, lb_max_set, npgfb, zetb, rpgfb, lb_min_set, lc_max_set, npgfc, zetc, rpgfc, lc_min_set, rab, dab, rac, dac, rbc, dbc, sabc, sdabc, sabdc, int_abc_ext)
Calculation of three-center overlap integrals [a|b|c] over primitive Cartesian Gaussian functions.
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Provides Cartesian and spherical orbital pointers and indices.
integer, dimension(:), allocatable, public ncoset
Methods used with 3-center overlap type integrals containers.
subroutine, public contract3_o3c(o3c, vec, matrix)
Contraction of 3-tensor over index 3 h(ij) = h(ij) + sum_k (ijk)*v(k)
subroutine, public calculate_o3c_integrals(o3c, calculate_forces, matrix_p)
...
subroutine, public contract12_o3c(o3c, matrix_p)
Contraction of 3-tensor over indices 1 and 2 (assuming symmetry) t(k) = sum_ij (ijk)*p(ij)
3-center overlap type integrals containers
subroutine, public set_o3c_container(o3c_iterator, mepos, integral, tvec, force_i, force_j, force_k)
...
subroutine, public get_o3c_iterator_info(o3c_iterator, mepos, iatom, jatom, katom, ikind, jkind, kkind, rij, rik, cellj, cellk, integral, tvec, force_i, force_j, force_k)
...
subroutine, public o3c_iterator_create(o3c, o3c_iterator, nthread)
...
subroutine, public o3c_iterator_release(o3c_iterator)
...
subroutine, public get_o3c_vec(o3c_vec, i, vec, n)
...
integer function, public o3c_iterate(o3c_iterator, mepos)
...
subroutine, public get_o3c_container(o3c, ijsymmetric, nspin, nijpairs, ijpair, basis_set_list_a, basis_set_list_b, basis_set_list_c, sab_nl, sac_nl)
...