(git:e7e05ae)
grid_api.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: BSD-3-Clause !
6 !--------------------------------------------------------------------------------------------------!
7 
8 ! **************************************************************************************************
9 !> \brief Fortran API for the grid package, which is written in C.
10 !> \author Ole Schuett
11 ! **************************************************************************************************
12 MODULE grid_api
13  USE iso_c_binding, ONLY: &
14  c_associated, c_bool, c_char, c_double, c_funloc, c_funptr, c_int, c_loc, c_long, &
15  c_null_ptr, c_ptr
16  USE kinds, ONLY: dp
17  USE message_passing, ONLY: mp_comm_type
18  USE offload_api, ONLY: offload_buffer_type
19  USE realspace_grid_types, ONLY: realspace_grid_type
20  USE string_utilities, ONLY: strlcpy_c2f
21 #include "../base/base_uses.f90"
22 
23  IMPLICIT NONE
24 
25  PRIVATE
26 
27  CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'grid_api'
28 
29  INTEGER, PARAMETER, PUBLIC :: grid_func_ab = 100
30  INTEGER, PARAMETER, PUBLIC :: grid_func_dadb = 200
31  INTEGER, PARAMETER, PUBLIC :: grid_func_adbmdab_x = 301
32  INTEGER, PARAMETER, PUBLIC :: grid_func_adbmdab_y = 302
33  INTEGER, PARAMETER, PUBLIC :: grid_func_adbmdab_z = 303
34  INTEGER, PARAMETER, PUBLIC :: grid_func_ardbmdarb_xx = 411
35  INTEGER, PARAMETER, PUBLIC :: grid_func_ardbmdarb_xy = 412
36  INTEGER, PARAMETER, PUBLIC :: grid_func_ardbmdarb_xz = 413
37  INTEGER, PARAMETER, PUBLIC :: grid_func_ardbmdarb_yx = 421
38  INTEGER, PARAMETER, PUBLIC :: grid_func_ardbmdarb_yy = 422
39  INTEGER, PARAMETER, PUBLIC :: grid_func_ardbmdarb_yz = 423
40  INTEGER, PARAMETER, PUBLIC :: grid_func_ardbmdarb_zx = 431
41  INTEGER, PARAMETER, PUBLIC :: grid_func_ardbmdarb_zy = 432
42  INTEGER, PARAMETER, PUBLIC :: grid_func_ardbmdarb_zz = 433
43  INTEGER, PARAMETER, PUBLIC :: grid_func_dabpadb_x = 501
44  INTEGER, PARAMETER, PUBLIC :: grid_func_dabpadb_y = 502
45  INTEGER, PARAMETER, PUBLIC :: grid_func_dabpadb_z = 503
46  INTEGER, PARAMETER, PUBLIC :: grid_func_dx = 601
47  INTEGER, PARAMETER, PUBLIC :: grid_func_dy = 602
48  INTEGER, PARAMETER, PUBLIC :: grid_func_dz = 603
49  INTEGER, PARAMETER, PUBLIC :: grid_func_dxdy = 701
50  INTEGER, PARAMETER, PUBLIC :: grid_func_dydz = 702
51  INTEGER, PARAMETER, PUBLIC :: grid_func_dzdx = 703
52  INTEGER, PARAMETER, PUBLIC :: grid_func_dxdx = 801
53  INTEGER, PARAMETER, PUBLIC :: grid_func_dydy = 802
54  INTEGER, PARAMETER, PUBLIC :: grid_func_dzdz = 803
55  INTEGER, PARAMETER, PUBLIC :: grid_func_dab_x = 901
56  INTEGER, PARAMETER, PUBLIC :: grid_func_dab_y = 902
57  INTEGER, PARAMETER, PUBLIC :: grid_func_dab_z = 903
58  INTEGER, PARAMETER, PUBLIC :: grid_func_adb_x = 904
59  INTEGER, PARAMETER, PUBLIC :: grid_func_adb_y = 905
60  INTEGER, PARAMETER, PUBLIC :: grid_func_adb_z = 906
61 
62  INTEGER, PARAMETER, PUBLIC :: grid_func_core_x = 1001
63  INTEGER, PARAMETER, PUBLIC :: grid_func_core_y = 1002
64  INTEGER, PARAMETER, PUBLIC :: grid_func_core_z = 1003
65 
66  INTEGER, PARAMETER, PUBLIC :: grid_backend_auto = 10
67  INTEGER, PARAMETER, PUBLIC :: grid_backend_ref = 11
68  INTEGER, PARAMETER, PUBLIC :: grid_backend_cpu = 12
69  INTEGER, PARAMETER, PUBLIC :: grid_backend_dgemm = 13
70  INTEGER, PARAMETER, PUBLIC :: grid_backend_gpu = 14
71  INTEGER, PARAMETER, PUBLIC :: grid_backend_hip = 15
72 
76  PUBLIC :: grid_basis_set_type, grid_create_basis_set, grid_free_basis_set
77  PUBLIC :: grid_task_list_type, grid_create_task_list, grid_free_task_list
79 
80  TYPE grid_basis_set_type
81  PRIVATE
82  TYPE(c_ptr) :: c_ptr = c_null_ptr
83  END TYPE grid_basis_set_type
84 
85  TYPE grid_task_list_type
86  PRIVATE
87  TYPE(c_ptr) :: c_ptr = c_null_ptr
88  END TYPE grid_task_list_type
89 
90 CONTAINS
91 
92 ! **************************************************************************************************
93 !> \brief low level collocation of primitive gaussian functions
94 !> \param la_max ...
95 !> \param zeta ...
96 !> \param la_min ...
97 !> \param lb_max ...
98 !> \param zetb ...
99 !> \param lb_min ...
100 !> \param ra ...
101 !> \param rab ...
102 !> \param scale ...
103 !> \param pab ...
104 !> \param o1 ...
105 !> \param o2 ...
106 !> \param rsgrid ...
107 !> \param ga_gb_function ...
108 !> \param radius ...
109 !> \param use_subpatch ...
110 !> \param subpatch_pattern ...
111 !> \author Ole Schuett
112 ! **************************************************************************************************
113  SUBROUTINE collocate_pgf_product(la_max, zeta, la_min, &
114  lb_max, zetb, lb_min, &
115  ra, rab, scale, pab, o1, o2, &
116  rsgrid, &
117  ga_gb_function, radius, &
118  use_subpatch, subpatch_pattern)
119 
120  INTEGER, INTENT(IN) :: la_max
121  REAL(kind=dp), INTENT(IN) :: zeta
122  INTEGER, INTENT(IN) :: la_min, lb_max
123  REAL(kind=dp), INTENT(IN) :: zetb
124  INTEGER, INTENT(IN) :: lb_min
125  REAL(kind=dp), DIMENSION(3), INTENT(IN), TARGET :: ra, rab
126  REAL(kind=dp), INTENT(IN) :: scale
127  REAL(kind=dp), DIMENSION(:, :), POINTER :: pab
128  INTEGER, INTENT(IN) :: o1, o2
129  TYPE(realspace_grid_type) :: rsgrid
130  INTEGER, INTENT(IN) :: ga_gb_function
131  REAL(kind=dp), INTENT(IN) :: radius
132  LOGICAL, OPTIONAL :: use_subpatch
133  INTEGER, INTENT(IN), OPTIONAL :: subpatch_pattern
134 
135  INTEGER :: border_mask
136  INTEGER, DIMENSION(3), TARGET :: border_width, npts_global, npts_local, &
137  shift_local
138  LOGICAL(KIND=C_BOOL) :: orthorhombic
139  REAL(kind=dp), DIMENSION(:, :, :), POINTER :: grid
140  INTERFACE
141  SUBROUTINE grid_cpu_collocate_pgf_product_c(orthorhombic, &
142  border_mask, func, &
143  la_max, la_min, lb_max, lb_min, &
144  zeta, zetb, rscale, dh, dh_inv, ra, rab, &
145  npts_global, npts_local, shift_local, border_width, &
146  radius, o1, o2, n1, n2, pab, &
147  grid) &
148  BIND(C, name="grid_cpu_collocate_pgf_product")
149  IMPORT :: c_ptr, c_int, c_double, c_bool
150  LOGICAL(KIND=C_BOOL), VALUE :: orthorhombic
151  INTEGER(KIND=C_INT), VALUE :: border_mask
152  INTEGER(KIND=C_INT), VALUE :: func
153  INTEGER(KIND=C_INT), VALUE :: la_max
154  INTEGER(KIND=C_INT), VALUE :: la_min
155  INTEGER(KIND=C_INT), VALUE :: lb_max
156  INTEGER(KIND=C_INT), VALUE :: lb_min
157  REAL(kind=c_double), VALUE :: zeta
158  REAL(kind=c_double), VALUE :: zetb
159  REAL(kind=c_double), VALUE :: rscale
160  TYPE(c_ptr), VALUE :: dh
161  TYPE(c_ptr), VALUE :: dh_inv
162  TYPE(c_ptr), VALUE :: ra
163  TYPE(c_ptr), VALUE :: rab
164  TYPE(c_ptr), VALUE :: npts_global
165  TYPE(c_ptr), VALUE :: npts_local
166  TYPE(c_ptr), VALUE :: shift_local
167  TYPE(c_ptr), VALUE :: border_width
168  REAL(kind=c_double), VALUE :: radius
169  INTEGER(KIND=C_INT), VALUE :: o1
170  INTEGER(KIND=C_INT), VALUE :: o2
171  INTEGER(KIND=C_INT), VALUE :: n1
172  INTEGER(KIND=C_INT), VALUE :: n2
173  TYPE(c_ptr), VALUE :: pab
174  TYPE(c_ptr), VALUE :: grid
175  END SUBROUTINE grid_cpu_collocate_pgf_product_c
176  END INTERFACE
177 
178  border_mask = 0
179  IF (PRESENT(use_subpatch)) THEN
180  IF (use_subpatch) THEN
181  cpassert(PRESENT(subpatch_pattern))
182  border_mask = iand(63, not(subpatch_pattern)) ! invert last 6 bits
183  END IF
184  END IF
185 
186  orthorhombic = LOGICAL(rsgrid%desc%orthorhombic, c_bool)
187 
188  cpassert(lbound(pab, 1) == 1)
189  cpassert(lbound(pab, 2) == 1)
190 
191  CALL get_rsgrid_properties(rsgrid, npts_global=npts_global, &
192  npts_local=npts_local, &
193  shift_local=shift_local, &
194  border_width=border_width)
195 
196  grid(1:, 1:, 1:) => rsgrid%r(:, :, :) ! pointer assignment
197 
198 #if __GNUC__ >= 9
199  cpassert(is_contiguous(rsgrid%desc%dh))
200  cpassert(is_contiguous(rsgrid%desc%dh_inv))
201  cpassert(is_contiguous(ra))
202  cpassert(is_contiguous(rab))
203  cpassert(is_contiguous(npts_global))
204  cpassert(is_contiguous(npts_local))
205  cpassert(is_contiguous(shift_local))
206  cpassert(is_contiguous(border_width))
207  cpassert(is_contiguous(pab))
208  cpassert(is_contiguous(grid))
209 #endif
210 
211  ! For collocating a single pgf product we use the optimized cpu backend.
212 
213  CALL grid_cpu_collocate_pgf_product_c(orthorhombic=orthorhombic, &
214  border_mask=border_mask, &
215  func=ga_gb_function, &
216  la_max=la_max, &
217  la_min=la_min, &
218  lb_max=lb_max, &
219  lb_min=lb_min, &
220  zeta=zeta, &
221  zetb=zetb, &
222  rscale=scale, &
223  dh=c_loc(rsgrid%desc%dh(1, 1)), &
224  dh_inv=c_loc(rsgrid%desc%dh_inv(1, 1)), &
225  ra=c_loc(ra(1)), &
226  rab=c_loc(rab(1)), &
227  npts_global=c_loc(npts_global(1)), &
228  npts_local=c_loc(npts_local(1)), &
229  shift_local=c_loc(shift_local(1)), &
230  border_width=c_loc(border_width(1)), &
231  radius=radius, &
232  o1=o1, &
233  o2=o2, &
234  n1=SIZE(pab, 1), &
235  n2=SIZE(pab, 2), &
236  pab=c_loc(pab(1, 1)), &
237  grid=c_loc(grid(1, 1, 1)))
238 
239  END SUBROUTINE collocate_pgf_product
240 
241 ! **************************************************************************************************
242 !> \brief low level function to compute matrix elements of primitive gaussian functions
243 !> \param la_max ...
244 !> \param zeta ...
245 !> \param la_min ...
246 !> \param lb_max ...
247 !> \param zetb ...
248 !> \param lb_min ...
249 !> \param ra ...
250 !> \param rab ...
251 !> \param rsgrid ...
252 !> \param hab ...
253 !> \param pab ...
254 !> \param o1 ...
255 !> \param o2 ...
256 !> \param radius ...
257 !> \param calculate_forces ...
258 !> \param force_a ...
259 !> \param force_b ...
260 !> \param compute_tau ...
261 !> \param use_virial ...
262 !> \param my_virial_a ...
263 !> \param my_virial_b ...
264 !> \param hdab Derivative with respect to the primitive on the left.
265 !> \param hadb Derivative with respect to the primitive on the right.
266 !> \param a_hdab ...
267 !> \param use_subpatch ...
268 !> \param subpatch_pattern ...
269 ! **************************************************************************************************
270  SUBROUTINE integrate_pgf_product(la_max, zeta, la_min, &
271  lb_max, zetb, lb_min, &
272  ra, rab, rsgrid, &
273  hab, pab, o1, o2, &
274  radius, &
275  calculate_forces, force_a, force_b, &
276  compute_tau, &
277  use_virial, my_virial_a, &
278  my_virial_b, hdab, hadb, a_hdab, use_subpatch, subpatch_pattern)
279 
280  INTEGER, INTENT(IN) :: la_max
281  REAL(kind=dp), INTENT(IN) :: zeta
282  INTEGER, INTENT(IN) :: la_min, lb_max
283  REAL(kind=dp), INTENT(IN) :: zetb
284  INTEGER, INTENT(IN) :: lb_min
285  REAL(kind=dp), DIMENSION(3), INTENT(IN), TARGET :: ra, rab
286  TYPE(realspace_grid_type), INTENT(IN) :: rsgrid
287  REAL(kind=dp), DIMENSION(:, :), POINTER :: hab
288  REAL(kind=dp), DIMENSION(:, :), OPTIONAL, POINTER :: pab
289  INTEGER, INTENT(IN) :: o1, o2
290  REAL(kind=dp), INTENT(IN) :: radius
291  LOGICAL, INTENT(IN) :: calculate_forces
292  REAL(kind=dp), DIMENSION(3), INTENT(INOUT), &
293  OPTIONAL :: force_a, force_b
294  LOGICAL, INTENT(IN), OPTIONAL :: compute_tau, use_virial
295  REAL(kind=dp), DIMENSION(3, 3), OPTIONAL :: my_virial_a, my_virial_b
296  REAL(kind=dp), DIMENSION(:, :, :), OPTIONAL, &
297  POINTER :: hdab, hadb
298  REAL(kind=dp), DIMENSION(:, :, :, :), OPTIONAL, &
299  POINTER :: a_hdab
300  LOGICAL, OPTIONAL :: use_subpatch
301  INTEGER, INTENT(IN), OPTIONAL :: subpatch_pattern
302 
303  INTEGER :: border_mask
304  INTEGER, DIMENSION(3), TARGET :: border_width, npts_global, npts_local, &
305  shift_local
306  LOGICAL :: my_use_virial
307  LOGICAL(KIND=C_BOOL) :: my_compute_tau, orthorhombic
308  REAL(kind=dp), DIMENSION(3, 2), TARGET :: forces
309  REAL(kind=dp), DIMENSION(3, 3, 2), TARGET :: virials
310  REAL(kind=dp), DIMENSION(:, :, :), POINTER :: grid
311  TYPE(c_ptr) :: a_hdab_cptr, forces_cptr, hadb_cptr, &
312  hdab_cptr, pab_cptr, virials_cptr
313  INTERFACE
314  SUBROUTINE grid_cpu_integrate_pgf_product_c(orthorhombic, compute_tau, &
315  border_mask, &
316  la_max, la_min, lb_max, lb_min, &
317  zeta, zetb, dh, dh_inv, ra, rab, &
318  npts_global, npts_local, shift_local, border_width, &
319  radius, o1, o2, n1, n2, grid, hab, pab, &
320  forces, virials, hdab, hadb, a_hdab) &
321  BIND(C, name="grid_cpu_integrate_pgf_product")
322  IMPORT :: c_ptr, c_int, c_double, c_bool
323  LOGICAL(KIND=C_BOOL), VALUE :: orthorhombic
324  LOGICAL(KIND=C_BOOL), VALUE :: compute_tau
325  INTEGER(KIND=C_INT), VALUE :: border_mask
326  INTEGER(KIND=C_INT), VALUE :: la_max
327  INTEGER(KIND=C_INT), VALUE :: la_min
328  INTEGER(KIND=C_INT), VALUE :: lb_max
329  INTEGER(KIND=C_INT), VALUE :: lb_min
330  REAL(kind=c_double), VALUE :: zeta
331  REAL(kind=c_double), VALUE :: zetb
332  TYPE(c_ptr), VALUE :: dh
333  TYPE(c_ptr), VALUE :: dh_inv
334  TYPE(c_ptr), VALUE :: ra
335  TYPE(c_ptr), VALUE :: rab
336  TYPE(c_ptr), VALUE :: npts_global
337  TYPE(c_ptr), VALUE :: npts_local
338  TYPE(c_ptr), VALUE :: shift_local
339  TYPE(c_ptr), VALUE :: border_width
340  REAL(kind=c_double), VALUE :: radius
341  INTEGER(KIND=C_INT), VALUE :: o1
342  INTEGER(KIND=C_INT), VALUE :: o2
343  INTEGER(KIND=C_INT), VALUE :: n1
344  INTEGER(KIND=C_INT), VALUE :: n2
345  TYPE(c_ptr), VALUE :: grid
346  TYPE(c_ptr), VALUE :: hab
347  TYPE(c_ptr), VALUE :: pab
348  TYPE(c_ptr), VALUE :: forces
349  TYPE(c_ptr), VALUE :: virials
350  TYPE(c_ptr), VALUE :: hdab
351  TYPE(c_ptr), VALUE :: hadb
352  TYPE(c_ptr), VALUE :: a_hdab
353  END SUBROUTINE grid_cpu_integrate_pgf_product_c
354  END INTERFACE
355 
356  IF (radius == 0.0_dp) THEN
357  RETURN
358  END IF
359 
360  border_mask = 0
361  IF (PRESENT(use_subpatch)) THEN
362  IF (use_subpatch) THEN
363  cpassert(PRESENT(subpatch_pattern))
364  border_mask = iand(63, not(subpatch_pattern)) ! invert last 6 bits
365  END IF
366  END IF
367 
368  ! When true then 0.5 * (nabla x_a).(v(r) nabla x_b) is computed.
369  IF (PRESENT(compute_tau)) THEN
370  my_compute_tau = LOGICAL(compute_tau, c_bool)
371  ELSE
372  my_compute_tau = .false.
373  END IF
374 
375  IF (PRESENT(use_virial)) THEN
376  my_use_virial = use_virial
377  ELSE
378  my_use_virial = .false.
379  END IF
380 
381  IF (calculate_forces) THEN
382  cpassert(PRESENT(pab))
383  pab_cptr = c_loc(pab(1, 1))
384  forces(:, :) = 0.0_dp
385  forces_cptr = c_loc(forces(1, 1))
386  ELSE
387  pab_cptr = c_null_ptr
388  forces_cptr = c_null_ptr
389  END IF
390 
391  IF (calculate_forces .AND. my_use_virial) THEN
392  virials(:, :, :) = 0.0_dp
393  virials_cptr = c_loc(virials(1, 1, 1))
394  ELSE
395  virials_cptr = c_null_ptr
396  END IF
397 
398  IF (calculate_forces .AND. PRESENT(hdab)) THEN
399  hdab_cptr = c_loc(hdab(1, 1, 1))
400  ELSE
401  hdab_cptr = c_null_ptr
402  END IF
403 
404  IF (calculate_forces .AND. PRESENT(hadb)) THEN
405  hadb_cptr = c_loc(hadb(1, 1, 1))
406  ELSE
407  hadb_cptr = c_null_ptr
408  END IF
409 
410  IF (calculate_forces .AND. my_use_virial .AND. PRESENT(a_hdab)) THEN
411  a_hdab_cptr = c_loc(a_hdab(1, 1, 1, 1))
412  ELSE
413  a_hdab_cptr = c_null_ptr
414  END IF
415 
416  orthorhombic = LOGICAL(rsgrid%desc%orthorhombic, c_bool)
417 
418  CALL get_rsgrid_properties(rsgrid, npts_global=npts_global, &
419  npts_local=npts_local, &
420  shift_local=shift_local, &
421  border_width=border_width)
422 
423  grid(1:, 1:, 1:) => rsgrid%r(:, :, :) ! pointer assignment
424 
425 #if __GNUC__ >= 9
426  cpassert(is_contiguous(rsgrid%desc%dh))
427  cpassert(is_contiguous(rsgrid%desc%dh_inv))
428  cpassert(is_contiguous(ra))
429  cpassert(is_contiguous(rab))
430  cpassert(is_contiguous(npts_global))
431  cpassert(is_contiguous(npts_local))
432  cpassert(is_contiguous(shift_local))
433  cpassert(is_contiguous(border_width))
434  cpassert(is_contiguous(grid))
435  cpassert(is_contiguous(hab))
436  cpassert(is_contiguous(forces))
437  cpassert(is_contiguous(virials))
438  IF (PRESENT(pab)) THEN
439  cpassert(is_contiguous(pab))
440  END IF
441  IF (PRESENT(hdab)) THEN
442  cpassert(is_contiguous(hdab))
443  END IF
444  IF (PRESENT(a_hdab)) THEN
445  cpassert(is_contiguous(a_hdab))
446  END IF
447 #endif
448 
449  CALL grid_cpu_integrate_pgf_product_c(orthorhombic=orthorhombic, &
450  compute_tau=my_compute_tau, &
451  border_mask=border_mask, &
452  la_max=la_max, &
453  la_min=la_min, &
454  lb_max=lb_max, &
455  lb_min=lb_min, &
456  zeta=zeta, &
457  zetb=zetb, &
458  dh=c_loc(rsgrid%desc%dh(1, 1)), &
459  dh_inv=c_loc(rsgrid%desc%dh_inv(1, 1)), &
460  ra=c_loc(ra(1)), &
461  rab=c_loc(rab(1)), &
462  npts_global=c_loc(npts_global(1)), &
463  npts_local=c_loc(npts_local(1)), &
464  shift_local=c_loc(shift_local(1)), &
465  border_width=c_loc(border_width(1)), &
466  radius=radius, &
467  o1=o1, &
468  o2=o2, &
469  n1=SIZE(hab, 1), &
470  n2=SIZE(hab, 2), &
471  grid=c_loc(grid(1, 1, 1)), &
472  hab=c_loc(hab(1, 1)), &
473  pab=pab_cptr, &
474  forces=forces_cptr, &
475  virials=virials_cptr, &
476  hdab=hdab_cptr, &
477  hadb=hadb_cptr, &
478  a_hdab=a_hdab_cptr)
479 
480  IF (PRESENT(force_a) .AND. c_associated(forces_cptr)) &
481  force_a = force_a + forces(:, 1)
482  IF (PRESENT(force_b) .AND. c_associated(forces_cptr)) &
483  force_b = force_b + forces(:, 2)
484  IF (PRESENT(my_virial_a) .AND. c_associated(virials_cptr)) &
485  my_virial_a = my_virial_a + virials(:, :, 1)
486  IF (PRESENT(my_virial_b) .AND. c_associated(virials_cptr)) &
487  my_virial_b = my_virial_b + virials(:, :, 2)
488 
489  END SUBROUTINE integrate_pgf_product
490 
491 ! **************************************************************************************************
492 !> \brief Helper routines for getting rsgrid properties and asserting underlying assumptions.
493 !> \param rsgrid ...
494 !> \param npts_global ...
495 !> \param npts_local ...
496 !> \param shift_local ...
497 !> \param border_width ...
498 !> \author Ole Schuett
499 ! **************************************************************************************************
500  SUBROUTINE get_rsgrid_properties(rsgrid, npts_global, npts_local, shift_local, border_width)
501  TYPE(realspace_grid_type), INTENT(IN) :: rsgrid
502  INTEGER, DIMENSION(:) :: npts_global, npts_local, shift_local, &
503  border_width
504 
505  INTEGER :: i
506 
507  ! See rs_grid_create() in ./src/pw/realspace_grid_types.F.
508  cpassert(lbound(rsgrid%r, 1) == rsgrid%lb_local(1))
509  cpassert(ubound(rsgrid%r, 1) == rsgrid%ub_local(1))
510  cpassert(lbound(rsgrid%r, 2) == rsgrid%lb_local(2))
511  cpassert(ubound(rsgrid%r, 2) == rsgrid%ub_local(2))
512  cpassert(lbound(rsgrid%r, 3) == rsgrid%lb_local(3))
513  cpassert(ubound(rsgrid%r, 3) == rsgrid%ub_local(3))
514 
515  ! While the rsgrid code assumes that the grid starts at rsgrid%lb,
516  ! the collocate code assumes that the grid starts at (1,1,1) in Fortran, or (0,0,0) in C.
517  ! So, a point rp(:) gets the following grid coordinates MODULO(rp(:)/dr(:),npts_global(:))
518 
519  ! Number of global grid points in each direction.
520  npts_global = rsgrid%desc%ub - rsgrid%desc%lb + 1
521 
522  ! Number of local grid points in each direction.
523  npts_local = rsgrid%ub_local - rsgrid%lb_local + 1
524 
525  ! Number of points the local grid is shifted wrt global grid.
526  shift_local = rsgrid%lb_local - rsgrid%desc%lb
527 
528  ! Convert rsgrid%desc%border and rsgrid%desc%perd into the more convenient border_width array.
529  DO i = 1, 3
530  IF (rsgrid%desc%perd(i) == 1) THEN
531  ! Periodic meaning the grid in this direction is entriely present on every processor.
532  cpassert(npts_local(i) == npts_global(i))
533  cpassert(shift_local(i) == 0)
534  ! No need for halo regions.
535  border_width(i) = 0
536  ELSE
537  ! Not periodic meaning the grid in this direction is distributed among processors.
538  cpassert(npts_local(i) <= npts_global(i))
539  ! Check bounds of grid section that is owned by this processor.
540  cpassert(rsgrid%lb_real(i) == rsgrid%lb_local(i) + rsgrid%desc%border)
541  cpassert(rsgrid%ub_real(i) == rsgrid%ub_local(i) - rsgrid%desc%border)
542  ! We have halo regions.
543  border_width(i) = rsgrid%desc%border
544  END IF
545  END DO
546  END SUBROUTINE get_rsgrid_properties
547 
548 ! **************************************************************************************************
549 !> \brief Allocates a basis set which can be passed to grid_create_task_list.
550 !> \param nset ...
551 !> \param nsgf ...
552 !> \param maxco ...
553 !> \param maxpgf ...
554 !> \param lmin ...
555 !> \param lmax ...
556 !> \param npgf ...
557 !> \param nsgf_set ...
558 !> \param first_sgf ...
559 !> \param sphi ...
560 !> \param zet ...
561 !> \param basis_set ...
562 !> \author Ole Schuett
563 ! **************************************************************************************************
564  SUBROUTINE grid_create_basis_set(nset, nsgf, maxco, maxpgf, &
565  lmin, lmax, npgf, nsgf_set, first_sgf, sphi, zet, &
566  basis_set)
567  INTEGER, INTENT(IN) :: nset, nsgf, maxco, maxpgf
568  INTEGER, DIMENSION(:), INTENT(IN), TARGET :: lmin, lmax, npgf, nsgf_set
569  INTEGER, DIMENSION(:, :), INTENT(IN) :: first_sgf
570  REAL(kind=dp), DIMENSION(:, :), INTENT(IN), TARGET :: sphi, zet
571  TYPE(grid_basis_set_type), INTENT(INOUT) :: basis_set
572 
573  CHARACTER(LEN=*), PARAMETER :: routinen = 'grid_create_basis_set'
574 
575  INTEGER :: handle
576  INTEGER, DIMENSION(nset), TARGET :: my_first_sgf
577  TYPE(c_ptr) :: first_sgf_c, lmax_c, lmin_c, npgf_c, &
578  nsgf_set_c, sphi_c, zet_c
579  INTERFACE
580  SUBROUTINE grid_create_basis_set_c(nset, nsgf, maxco, maxpgf, &
581  lmin, lmax, npgf, nsgf_set, first_sgf, sphi, zet, &
582  basis_set) &
583  BIND(C, name="grid_create_basis_set")
584  IMPORT :: c_ptr, c_int
585  INTEGER(KIND=C_INT), VALUE :: nset
586  INTEGER(KIND=C_INT), VALUE :: nsgf
587  INTEGER(KIND=C_INT), VALUE :: maxco
588  INTEGER(KIND=C_INT), VALUE :: maxpgf
589  TYPE(c_ptr), VALUE :: lmin
590  TYPE(c_ptr), VALUE :: lmax
591  TYPE(c_ptr), VALUE :: npgf
592  TYPE(c_ptr), VALUE :: nsgf_set
593  TYPE(c_ptr), VALUE :: first_sgf
594  TYPE(c_ptr), VALUE :: sphi
595  TYPE(c_ptr), VALUE :: zet
596  TYPE(c_ptr) :: basis_set
597  END SUBROUTINE grid_create_basis_set_c
598  END INTERFACE
599 
600  CALL timeset(routinen, handle)
601 
602  cpassert(SIZE(lmin) == nset)
603  cpassert(SIZE(lmin) == nset)
604  cpassert(SIZE(lmax) == nset)
605  cpassert(SIZE(npgf) == nset)
606  cpassert(SIZE(nsgf_set) == nset)
607  cpassert(SIZE(first_sgf, 2) == nset)
608  cpassert(SIZE(sphi, 1) == maxco .AND. SIZE(sphi, 2) == nsgf)
609  cpassert(SIZE(zet, 1) == maxpgf .AND. SIZE(zet, 2) == nset)
610  cpassert(.NOT. c_associated(basis_set%c_ptr))
611 
612 #if __GNUC__ >= 9
613  cpassert(is_contiguous(lmin))
614  cpassert(is_contiguous(lmax))
615  cpassert(is_contiguous(npgf))
616  cpassert(is_contiguous(nsgf_set))
617  cpassert(is_contiguous(my_first_sgf))
618  cpassert(is_contiguous(sphi))
619  cpassert(is_contiguous(zet))
620 #endif
621 
622  lmin_c = c_null_ptr
623  lmax_c = c_null_ptr
624  npgf_c = c_null_ptr
625  nsgf_set_c = c_null_ptr
626  first_sgf_c = c_null_ptr
627  sphi_c = c_null_ptr
628  zet_c = c_null_ptr
629 
630  ! Basis sets arrays can be empty, need to check before accessing the first element.
631  IF (nset > 0) THEN
632  lmin_c = c_loc(lmin(1))
633  lmax_c = c_loc(lmax(1))
634  npgf_c = c_loc(npgf(1))
635  nsgf_set_c = c_loc(nsgf_set(1))
636  END IF
637  IF (SIZE(first_sgf) > 0) THEN
638  my_first_sgf(:) = first_sgf(1, :) ! make a contiguous copy
639  first_sgf_c = c_loc(my_first_sgf(1))
640  END IF
641  IF (SIZE(sphi) > 0) THEN
642  sphi_c = c_loc(sphi(1, 1))
643  END IF
644  IF (SIZE(zet) > 0) THEN
645  zet_c = c_loc(zet(1, 1))
646  END IF
647 
648  CALL grid_create_basis_set_c(nset=nset, &
649  nsgf=nsgf, &
650  maxco=maxco, &
651  maxpgf=maxpgf, &
652  lmin=lmin_c, &
653  lmax=lmax_c, &
654  npgf=npgf_c, &
655  nsgf_set=nsgf_set_c, &
656  first_sgf=first_sgf_c, &
657  sphi=sphi_c, &
658  zet=zet_c, &
659  basis_set=basis_set%c_ptr)
660  cpassert(c_associated(basis_set%c_ptr))
661 
662  CALL timestop(handle)
663  END SUBROUTINE grid_create_basis_set
664 
665 ! **************************************************************************************************
666 !> \brief Deallocates given basis set.
667 !> \param basis_set ...
668 !> \author Ole Schuett
669 ! **************************************************************************************************
670  SUBROUTINE grid_free_basis_set(basis_set)
671  TYPE(grid_basis_set_type), INTENT(INOUT) :: basis_set
672 
673  CHARACTER(LEN=*), PARAMETER :: routinen = 'grid_free_basis_set'
674 
675  INTEGER :: handle
676  INTERFACE
677  SUBROUTINE grid_free_basis_set_c(basis_set) &
678  BIND(C, name="grid_free_basis_set")
679  IMPORT :: c_ptr
680  TYPE(c_ptr), VALUE :: basis_set
681  END SUBROUTINE grid_free_basis_set_c
682  END INTERFACE
683 
684  CALL timeset(routinen, handle)
685 
686  cpassert(c_associated(basis_set%c_ptr))
687 
688  CALL grid_free_basis_set_c(basis_set%c_ptr)
689 
690  basis_set%c_ptr = c_null_ptr
691 
692  CALL timestop(handle)
693  END SUBROUTINE grid_free_basis_set
694 
695 ! **************************************************************************************************
696 !> \brief Allocates a task list which can be passed to grid_collocate_task_list.
697 !> \param ntasks ...
698 !> \param natoms ...
699 !> \param nkinds ...
700 !> \param nblocks ...
701 !> \param block_offsets ...
702 !> \param atom_positions ...
703 !> \param atom_kinds ...
704 !> \param basis_sets ...
705 !> \param level_list ...
706 !> \param iatom_list ...
707 !> \param jatom_list ...
708 !> \param iset_list ...
709 !> \param jset_list ...
710 !> \param ipgf_list ...
711 !> \param jpgf_list ...
712 !> \param border_mask_list ...
713 !> \param block_num_list ...
714 !> \param radius_list ...
715 !> \param rab_list ...
716 !> \param rs_grids ...
717 !> \param task_list ...
718 !> \author Ole Schuett
719 ! **************************************************************************************************
720  SUBROUTINE grid_create_task_list(ntasks, natoms, nkinds, nblocks, &
721  block_offsets, atom_positions, atom_kinds, basis_sets, &
722  level_list, iatom_list, jatom_list, &
723  iset_list, jset_list, ipgf_list, jpgf_list, &
724  border_mask_list, block_num_list, &
725  radius_list, rab_list, rs_grids, task_list)
726 
727  INTEGER, INTENT(IN) :: ntasks, natoms, nkinds, nblocks
728  INTEGER, DIMENSION(:), INTENT(IN), TARGET :: block_offsets
729  REAL(kind=dp), DIMENSION(:, :), INTENT(IN), TARGET :: atom_positions
730  INTEGER, DIMENSION(:), INTENT(IN), TARGET :: atom_kinds
731  TYPE(grid_basis_set_type), DIMENSION(:), &
732  INTENT(IN), TARGET :: basis_sets
733  INTEGER, DIMENSION(:), INTENT(IN), TARGET :: level_list, iatom_list, jatom_list, &
734  iset_list, jset_list, ipgf_list, &
735  jpgf_list, border_mask_list, &
736  block_num_list
737  REAL(kind=dp), DIMENSION(:), INTENT(IN), TARGET :: radius_list
738  REAL(kind=dp), DIMENSION(:, :), INTENT(IN), TARGET :: rab_list
739  TYPE(realspace_grid_type), DIMENSION(:), &
740  INTENT(IN) :: rs_grids
741  TYPE(grid_task_list_type), INTENT(INOUT) :: task_list
742 
743  CHARACTER(LEN=*), PARAMETER :: routinen = 'grid_create_task_list'
744 
745  INTEGER :: handle, ikind, ilevel, nlevels
746  INTEGER, ALLOCATABLE, DIMENSION(:, :), TARGET :: border_width, npts_global, npts_local, &
747  shift_local
748  LOGICAL(KIND=C_BOOL) :: orthorhombic
749  REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :), &
750  TARGET :: dh, dh_inv
751  TYPE(c_ptr) :: block_num_list_c, block_offsets_c, border_mask_list_c, iatom_list_c, &
752  ipgf_list_c, iset_list_c, jatom_list_c, jpgf_list_c, jset_list_c, level_list_c, &
753  rab_list_c, radius_list_c
754  TYPE(c_ptr), ALLOCATABLE, DIMENSION(:), TARGET :: basis_sets_c
755  INTERFACE
756  SUBROUTINE grid_create_task_list_c(orthorhombic, &
757  ntasks, nlevels, natoms, nkinds, nblocks, &
758  block_offsets, atom_positions, atom_kinds, basis_sets, &
759  level_list, iatom_list, jatom_list, &
760  iset_list, jset_list, ipgf_list, jpgf_list, &
761  border_mask_list, block_num_list, &
762  radius_list, rab_list, &
763  npts_global, npts_local, shift_local, &
764  border_width, dh, dh_inv, task_list) &
765  BIND(C, name="grid_create_task_list")
766  IMPORT :: c_ptr, c_int, c_bool
767  LOGICAL(KIND=C_BOOL), VALUE :: orthorhombic
768  INTEGER(KIND=C_INT), VALUE :: ntasks
769  INTEGER(KIND=C_INT), VALUE :: nlevels
770  INTEGER(KIND=C_INT), VALUE :: natoms
771  INTEGER(KIND=C_INT), VALUE :: nkinds
772  INTEGER(KIND=C_INT), VALUE :: nblocks
773  TYPE(c_ptr), VALUE :: block_offsets
774  TYPE(c_ptr), VALUE :: atom_positions
775  TYPE(c_ptr), VALUE :: atom_kinds
776  TYPE(c_ptr), VALUE :: basis_sets
777  TYPE(c_ptr), VALUE :: level_list
778  TYPE(c_ptr), VALUE :: iatom_list
779  TYPE(c_ptr), VALUE :: jatom_list
780  TYPE(c_ptr), VALUE :: iset_list
781  TYPE(c_ptr), VALUE :: jset_list
782  TYPE(c_ptr), VALUE :: ipgf_list
783  TYPE(c_ptr), VALUE :: jpgf_list
784  TYPE(c_ptr), VALUE :: border_mask_list
785  TYPE(c_ptr), VALUE :: block_num_list
786  TYPE(c_ptr), VALUE :: radius_list
787  TYPE(c_ptr), VALUE :: rab_list
788  TYPE(c_ptr), VALUE :: npts_global
789  TYPE(c_ptr), VALUE :: npts_local
790  TYPE(c_ptr), VALUE :: shift_local
791  TYPE(c_ptr), VALUE :: border_width
792  TYPE(c_ptr), VALUE :: dh
793  TYPE(c_ptr), VALUE :: dh_inv
794  TYPE(c_ptr) :: task_list
795  END SUBROUTINE grid_create_task_list_c
796  END INTERFACE
797 
798  CALL timeset(routinen, handle)
799 
800  cpassert(SIZE(block_offsets) == nblocks)
801  cpassert(SIZE(atom_positions, 1) == 3 .AND. SIZE(atom_positions, 2) == natoms)
802  cpassert(SIZE(atom_kinds) == natoms)
803  cpassert(SIZE(basis_sets) == nkinds)
804  cpassert(SIZE(level_list) == ntasks)
805  cpassert(SIZE(iatom_list) == ntasks)
806  cpassert(SIZE(jatom_list) == ntasks)
807  cpassert(SIZE(iset_list) == ntasks)
808  cpassert(SIZE(jset_list) == ntasks)
809  cpassert(SIZE(ipgf_list) == ntasks)
810  cpassert(SIZE(jpgf_list) == ntasks)
811  cpassert(SIZE(border_mask_list) == ntasks)
812  cpassert(SIZE(block_num_list) == ntasks)
813  cpassert(SIZE(radius_list) == ntasks)
814  cpassert(SIZE(rab_list, 1) == 3 .AND. SIZE(rab_list, 2) == ntasks)
815 
816  ALLOCATE (basis_sets_c(nkinds))
817  DO ikind = 1, nkinds
818  basis_sets_c(ikind) = basis_sets(ikind)%c_ptr
819  END DO
820 
821  nlevels = SIZE(rs_grids)
822  cpassert(nlevels > 0)
823  orthorhombic = LOGICAL(rs_grids(1)%desc%orthorhombic, c_bool)
824 
825  ALLOCATE (npts_global(3, nlevels), npts_local(3, nlevels))
826  ALLOCATE (shift_local(3, nlevels), border_width(3, nlevels))
827  ALLOCATE (dh(3, 3, nlevels), dh_inv(3, 3, nlevels))
828  DO ilevel = 1, nlevels
829  associate(rsgrid => rs_grids(ilevel))
830  CALL get_rsgrid_properties(rsgrid=rsgrid, &
831  npts_global=npts_global(:, ilevel), &
832  npts_local=npts_local(:, ilevel), &
833  shift_local=shift_local(:, ilevel), &
834  border_width=border_width(:, ilevel))
835  cpassert(rsgrid%desc%orthorhombic .EQV. orthorhombic) ! should be the same for all levels
836  dh(:, :, ilevel) = rsgrid%desc%dh(:, :)
837  dh_inv(:, :, ilevel) = rsgrid%desc%dh_inv(:, :)
838  END associate
839  END DO
840 
841 #if __GNUC__ >= 9
842  cpassert(is_contiguous(block_offsets))
843  cpassert(is_contiguous(atom_positions))
844  cpassert(is_contiguous(atom_kinds))
845  cpassert(is_contiguous(basis_sets))
846  cpassert(is_contiguous(level_list))
847  cpassert(is_contiguous(iatom_list))
848  cpassert(is_contiguous(jatom_list))
849  cpassert(is_contiguous(iset_list))
850  cpassert(is_contiguous(jset_list))
851  cpassert(is_contiguous(ipgf_list))
852  cpassert(is_contiguous(jpgf_list))
853  cpassert(is_contiguous(border_mask_list))
854  cpassert(is_contiguous(block_num_list))
855  cpassert(is_contiguous(radius_list))
856  cpassert(is_contiguous(rab_list))
857  cpassert(is_contiguous(npts_global))
858  cpassert(is_contiguous(npts_local))
859  cpassert(is_contiguous(shift_local))
860  cpassert(is_contiguous(border_width))
861  cpassert(is_contiguous(dh))
862  cpassert(is_contiguous(dh_inv))
863 #endif
864 
865  IF (ntasks > 0) THEN
866  block_offsets_c = c_loc(block_offsets(1))
867  level_list_c = c_loc(level_list(1))
868  iatom_list_c = c_loc(iatom_list(1))
869  jatom_list_c = c_loc(jatom_list(1))
870  iset_list_c = c_loc(iset_list(1))
871  jset_list_c = c_loc(jset_list(1))
872  ipgf_list_c = c_loc(ipgf_list(1))
873  jpgf_list_c = c_loc(jpgf_list(1))
874  border_mask_list_c = c_loc(border_mask_list(1))
875  block_num_list_c = c_loc(block_num_list(1))
876  radius_list_c = c_loc(radius_list(1))
877  rab_list_c = c_loc(rab_list(1, 1))
878  ELSE
879  ! Without tasks the lists are empty and there is no first element to call C_LOC on.
880  block_offsets_c = c_null_ptr
881  level_list_c = c_null_ptr
882  iatom_list_c = c_null_ptr
883  jatom_list_c = c_null_ptr
884  iset_list_c = c_null_ptr
885  jset_list_c = c_null_ptr
886  ipgf_list_c = c_null_ptr
887  jpgf_list_c = c_null_ptr
888  border_mask_list_c = c_null_ptr
889  block_num_list_c = c_null_ptr
890  radius_list_c = c_null_ptr
891  rab_list_c = c_null_ptr
892  END IF
893 
894  !If task_list%c_ptr is already allocated, then its memory will be reused or freed.
895  CALL grid_create_task_list_c(orthorhombic=orthorhombic, &
896  ntasks=ntasks, &
897  nlevels=nlevels, &
898  natoms=natoms, &
899  nkinds=nkinds, &
900  nblocks=nblocks, &
901  block_offsets=block_offsets_c, &
902  atom_positions=c_loc(atom_positions(1, 1)), &
903  atom_kinds=c_loc(atom_kinds(1)), &
904  basis_sets=c_loc(basis_sets_c(1)), &
905  level_list=level_list_c, &
906  iatom_list=iatom_list_c, &
907  jatom_list=jatom_list_c, &
908  iset_list=iset_list_c, &
909  jset_list=jset_list_c, &
910  ipgf_list=ipgf_list_c, &
911  jpgf_list=jpgf_list_c, &
912  border_mask_list=border_mask_list_c, &
913  block_num_list=block_num_list_c, &
914  radius_list=radius_list_c, &
915  rab_list=rab_list_c, &
916  npts_global=c_loc(npts_global(1, 1)), &
917  npts_local=c_loc(npts_local(1, 1)), &
918  shift_local=c_loc(shift_local(1, 1)), &
919  border_width=c_loc(border_width(1, 1)), &
920  dh=c_loc(dh(1, 1, 1)), &
921  dh_inv=c_loc(dh_inv(1, 1, 1)), &
922  task_list=task_list%c_ptr)
923 
924  cpassert(c_associated(task_list%c_ptr))
925 
926  CALL timestop(handle)
927  END SUBROUTINE grid_create_task_list
928 
929 ! **************************************************************************************************
930 !> \brief Deallocates given task list, basis_sets have to be freed separately.
931 !> \param task_list ...
932 !> \author Ole Schuett
933 ! **************************************************************************************************
934  SUBROUTINE grid_free_task_list(task_list)
935  TYPE(grid_task_list_type), INTENT(INOUT) :: task_list
936 
937  CHARACTER(LEN=*), PARAMETER :: routinen = 'grid_free_task_list'
938 
939  INTEGER :: handle
940  INTERFACE
941  SUBROUTINE grid_free_task_list_c(task_list) &
942  BIND(C, name="grid_free_task_list")
943  IMPORT :: c_ptr
944  TYPE(c_ptr), VALUE :: task_list
945  END SUBROUTINE grid_free_task_list_c
946  END INTERFACE
947 
948  CALL timeset(routinen, handle)
949 
950  IF (c_associated(task_list%c_ptr)) THEN
951  CALL grid_free_task_list_c(task_list%c_ptr)
952  END IF
953 
954  task_list%c_ptr = c_null_ptr
955 
956  CALL timestop(handle)
957  END SUBROUTINE grid_free_task_list
958 
959 ! **************************************************************************************************
960 !> \brief Collocate all tasks of in given list onto given grids.
961 !> \param task_list ...
962 !> \param ga_gb_function ...
963 !> \param pab_blocks ...
964 !> \param rs_grids ...
965 !> \author Ole Schuett
966 ! **************************************************************************************************
967  SUBROUTINE grid_collocate_task_list(task_list, ga_gb_function, pab_blocks, rs_grids)
968  TYPE(grid_task_list_type), INTENT(IN) :: task_list
969  INTEGER, INTENT(IN) :: ga_gb_function
970  TYPE(offload_buffer_type), INTENT(IN) :: pab_blocks
971  TYPE(realspace_grid_type), DIMENSION(:), &
972  INTENT(IN) :: rs_grids
973 
974  CHARACTER(LEN=*), PARAMETER :: routinen = 'grid_collocate_task_list'
975 
976  INTEGER :: handle, ilevel, nlevels
977  INTEGER, ALLOCATABLE, DIMENSION(:, :), TARGET :: npts_local
978  TYPE(c_ptr), ALLOCATABLE, DIMENSION(:), TARGET :: grids_c
979  INTERFACE
980  SUBROUTINE grid_collocate_task_list_c(task_list, func, nlevels, &
981  npts_local, pab_blocks, grids) &
982  BIND(C, name="grid_collocate_task_list")
983  IMPORT :: c_ptr, c_int, c_bool
984  TYPE(c_ptr), VALUE :: task_list
985  INTEGER(KIND=C_INT), VALUE :: func
986  INTEGER(KIND=C_INT), VALUE :: nlevels
987  TYPE(c_ptr), VALUE :: npts_local
988  TYPE(c_ptr), VALUE :: pab_blocks
989  TYPE(c_ptr), VALUE :: grids
990  END SUBROUTINE grid_collocate_task_list_c
991  END INTERFACE
992 
993  CALL timeset(routinen, handle)
994 
995  nlevels = SIZE(rs_grids)
996  cpassert(nlevels > 0)
997 
998  ALLOCATE (grids_c(nlevels))
999  ALLOCATE (npts_local(3, nlevels))
1000  DO ilevel = 1, nlevels
1001  associate(rsgrid => rs_grids(ilevel))
1002  npts_local(:, ilevel) = rsgrid%ub_local - rsgrid%lb_local + 1
1003  grids_c(ilevel) = rsgrid%buffer%c_ptr
1004  END associate
1005  END DO
1006 
1007 #if __GNUC__ >= 9
1008  cpassert(is_contiguous(npts_local))
1009  cpassert(is_contiguous(grids_c))
1010 #endif
1011 
1012  cpassert(c_associated(task_list%c_ptr))
1013  cpassert(c_associated(pab_blocks%c_ptr))
1014 
1015  CALL grid_collocate_task_list_c(task_list=task_list%c_ptr, &
1016  func=ga_gb_function, &
1017  nlevels=nlevels, &
1018  npts_local=c_loc(npts_local(1, 1)), &
1019  pab_blocks=pab_blocks%c_ptr, &
1020  grids=c_loc(grids_c(1)))
1021 
1022  CALL timestop(handle)
1023  END SUBROUTINE grid_collocate_task_list
1024 
1025 ! **************************************************************************************************
1026 !> \brief Integrate all tasks of in given list from given grids.
1027 !> \param task_list ...
1028 !> \param compute_tau ...
1029 !> \param calculate_forces ...
1030 !> \param calculate_virial ...
1031 !> \param pab_blocks ...
1032 !> \param rs_grids ...
1033 !> \param hab_blocks ...
1034 !> \param forces ...
1035 !> \param virial ...
1036 !> \author Ole Schuett
1037 ! **************************************************************************************************
1038  SUBROUTINE grid_integrate_task_list(task_list, compute_tau, calculate_forces, calculate_virial, &
1039  pab_blocks, rs_grids, hab_blocks, forces, virial)
1040  TYPE(grid_task_list_type), INTENT(IN) :: task_list
1041  LOGICAL, INTENT(IN) :: compute_tau, calculate_forces, &
1042  calculate_virial
1043  TYPE(offload_buffer_type), INTENT(IN) :: pab_blocks
1044  TYPE(realspace_grid_type), DIMENSION(:), &
1045  INTENT(IN) :: rs_grids
1046  TYPE(offload_buffer_type), INTENT(INOUT) :: hab_blocks
1047  REAL(kind=dp), DIMENSION(:, :), INTENT(INOUT), &
1048  TARGET :: forces
1049  REAL(kind=dp), DIMENSION(3, 3), INTENT(INOUT), &
1050  TARGET :: virial
1051 
1052  CHARACTER(LEN=*), PARAMETER :: routinen = 'grid_integrate_task_list'
1053 
1054  INTEGER :: handle, ilevel, nlevels
1055  INTEGER, ALLOCATABLE, DIMENSION(:, :), TARGET :: npts_local
1056  TYPE(c_ptr) :: forces_c, virial_c
1057  TYPE(c_ptr), ALLOCATABLE, DIMENSION(:), TARGET :: grids_c
1058  INTERFACE
1059  SUBROUTINE grid_integrate_task_list_c(task_list, compute_tau, natoms, &
1060  nlevels, npts_local, &
1061  pab_blocks, grids, hab_blocks, forces, virial) &
1062  BIND(C, name="grid_integrate_task_list")
1063  IMPORT :: c_ptr, c_int, c_bool
1064  TYPE(c_ptr), VALUE :: task_list
1065  LOGICAL(KIND=C_BOOL), VALUE :: compute_tau
1066  INTEGER(KIND=C_INT), VALUE :: natoms
1067  INTEGER(KIND=C_INT), VALUE :: nlevels
1068  TYPE(c_ptr), VALUE :: npts_local
1069  TYPE(c_ptr), VALUE :: pab_blocks
1070  TYPE(c_ptr), VALUE :: grids
1071  TYPE(c_ptr), VALUE :: hab_blocks
1072  TYPE(c_ptr), VALUE :: forces
1073  TYPE(c_ptr), VALUE :: virial
1074  END SUBROUTINE grid_integrate_task_list_c
1075  END INTERFACE
1076 
1077  CALL timeset(routinen, handle)
1078 
1079  nlevels = SIZE(rs_grids)
1080  cpassert(nlevels > 0)
1081 
1082  ALLOCATE (grids_c(nlevels))
1083  ALLOCATE (npts_local(3, nlevels))
1084  DO ilevel = 1, nlevels
1085  associate(rsgrid => rs_grids(ilevel))
1086  npts_local(:, ilevel) = rsgrid%ub_local - rsgrid%lb_local + 1
1087  grids_c(ilevel) = rsgrid%buffer%c_ptr
1088  END associate
1089  END DO
1090 
1091  IF (calculate_forces) THEN
1092  forces_c = c_loc(forces(1, 1))
1093  ELSE
1094  forces_c = c_null_ptr
1095  END IF
1096 
1097  IF (calculate_virial) THEN
1098  virial_c = c_loc(virial(1, 1))
1099  ELSE
1100  virial_c = c_null_ptr
1101  END IF
1102 
1103 #if __GNUC__ >= 9
1104  cpassert(is_contiguous(npts_local))
1105  cpassert(is_contiguous(grids_c))
1106  cpassert(is_contiguous(forces))
1107  cpassert(is_contiguous(virial))
1108 #endif
1109 
1110  cpassert(SIZE(forces, 1) == 3)
1111  cpassert(c_associated(task_list%c_ptr))
1112  cpassert(c_associated(hab_blocks%c_ptr))
1113  cpassert(c_associated(pab_blocks%c_ptr) .OR. .NOT. calculate_forces)
1114  cpassert(c_associated(pab_blocks%c_ptr) .OR. .NOT. calculate_virial)
1115 
1116  CALL grid_integrate_task_list_c(task_list=task_list%c_ptr, &
1117  compute_tau=LOGICAL(compute_tau, C_BOOL), &
1118  natoms=size(forces, 2), &
1119  nlevels=nlevels, &
1120  npts_local=c_loc(npts_local(1, 1)), &
1121  pab_blocks=pab_blocks%c_ptr, &
1122  grids=c_loc(grids_c(1)), &
1123  hab_blocks=hab_blocks%c_ptr, &
1124  forces=forces_c, &
1125  virial=virial_c)
1126 
1127  CALL timestop(handle)
1128  END SUBROUTINE grid_integrate_task_list
1129 
1130 ! **************************************************************************************************
1131 !> \brief Initialize grid library
1132 !> \author Ole Schuett
1133 ! **************************************************************************************************
1134  SUBROUTINE grid_library_init()
1135  INTERFACE
1136  SUBROUTINE grid_library_init_c() BIND(C, name="grid_library_init")
1137  END SUBROUTINE grid_library_init_c
1138  END INTERFACE
1139 
1140  CALL grid_library_init_c()
1141 
1142  END SUBROUTINE grid_library_init
1143 
1144 ! **************************************************************************************************
1145 !> \brief Finalize grid library
1146 !> \author Ole Schuett
1147 ! **************************************************************************************************
1149  INTERFACE
1150  SUBROUTINE grid_library_finalize_c() BIND(C, name="grid_library_finalize")
1151  END SUBROUTINE grid_library_finalize_c
1152  END INTERFACE
1153 
1154  CALL grid_library_finalize_c()
1155 
1156  END SUBROUTINE grid_library_finalize
1157 
1158 ! **************************************************************************************************
1159 !> \brief Configures the grid library
1160 !> \param backend : backend to be used for collocate/integrate, possible values are REF, CPU, GPU
1161 !> \param validate : if set to true, compare the results of all backend to the reference backend
1162 !> \param apply_cutoff : apply a spherical cutoff before collocating or integrating. Only relevant for CPU backend
1163 !> \author Ole Schuett
1164 ! **************************************************************************************************
1165  SUBROUTINE grid_library_set_config(backend, validate, apply_cutoff)
1166  INTEGER, INTENT(IN) :: backend
1167  LOGICAL, INTENT(IN) :: validate, apply_cutoff
1168 
1169  INTERFACE
1170  SUBROUTINE grid_library_set_config_c(backend, validate, apply_cutoff) &
1171  BIND(C, name="grid_library_set_config")
1172  IMPORT :: c_int, c_bool
1173  INTEGER(KIND=C_INT), VALUE :: backend
1174  LOGICAL(KIND=C_BOOL), VALUE :: validate
1175  LOGICAL(KIND=C_BOOL), VALUE :: apply_cutoff
1176  END SUBROUTINE grid_library_set_config_c
1177  END INTERFACE
1178 
1179  CALL grid_library_set_config_c(backend=backend, &
1180  validate=LOGICAL(validate, C_BOOL), &
1181  apply_cutoff=logical(apply_cutoff, c_bool))
1182 
1183  END SUBROUTINE grid_library_set_config
1184 
1185 ! **************************************************************************************************
1186 !> \brief Print grid library statistics
1187 !> \param mpi_comm ...
1188 !> \param output_unit ...
1189 !> \author Ole Schuett
1190 ! **************************************************************************************************
1191  SUBROUTINE grid_library_print_stats(mpi_comm, output_unit)
1192  TYPE(mp_comm_type) :: mpi_comm
1193  INTEGER, INTENT(IN) :: output_unit
1194 
1195  INTERFACE
1196  SUBROUTINE grid_library_print_stats_c(mpi_sum_func, mpi_comm, print_func, output_unit) &
1197  BIND(C, name="grid_library_print_stats")
1198  IMPORT :: c_funptr, c_int
1199  TYPE(c_funptr), VALUE :: mpi_sum_func
1200  INTEGER(KIND=C_INT), VALUE :: mpi_comm
1201  TYPE(c_funptr), VALUE :: print_func
1202  INTEGER(KIND=C_INT), VALUE :: output_unit
1203  END SUBROUTINE grid_library_print_stats_c
1204  END INTERFACE
1205 
1206  ! Since Fortran units and mpi groups can't be used from C, we pass function pointers instead.
1207  CALL grid_library_print_stats_c(mpi_sum_func=c_funloc(mpi_sum_func), &
1208  mpi_comm=mpi_comm%get_handle(), &
1209  print_func=c_funloc(print_func), &
1210  output_unit=output_unit)
1211 
1212  END SUBROUTINE grid_library_print_stats
1213 
1214 ! **************************************************************************************************
1215 !> \brief Callback to run mpi_sum on a Fortran MPI communicator.
1216 !> \param number ...
1217 !> \param mpi_comm ...
1218 !> \author Ole Schuett
1219 ! **************************************************************************************************
1220  SUBROUTINE mpi_sum_func(number, mpi_comm) BIND(C, name="grid_api_mpi_sum_func")
1221  INTEGER(KIND=C_LONG), INTENT(INOUT) :: number
1222  INTEGER(KIND=C_INT), INTENT(IN), VALUE :: mpi_comm
1223 
1224  TYPE(mp_comm_type) :: my_mpi_comm
1225 
1226  ! Convert the handle to the default integer kind and convert it to the communicator type
1227  CALL my_mpi_comm%set_handle(int(mpi_comm))
1228 
1229  CALL my_mpi_comm%sum(number)
1230  END SUBROUTINE mpi_sum_func
1231 
1232 ! **************************************************************************************************
1233 !> \brief Callback to write to a Fortran output unit.
1234 !> \param message ...
1235 !> \param output_unit ...
1236 !> \author Ole Schuett
1237 ! **************************************************************************************************
1238  SUBROUTINE print_func(message, output_unit) BIND(C, name="grid_api_print_func")
1239  CHARACTER(LEN=1, KIND=C_CHAR), INTENT(IN) :: message(*)
1240  INTEGER(KIND=C_INT), INTENT(IN), VALUE :: output_unit
1241 
1242  CHARACTER(LEN=1000) :: buffer
1243  INTEGER :: nchars
1244 
1245  IF (output_unit <= 0) &
1246  RETURN
1247 
1248  ! Convert C char array into Fortran string.
1249  nchars = strlcpy_c2f(buffer, message)
1250 
1251  ! Print the message.
1252  WRITE (output_unit, fmt="(A)", advance="NO") buffer(1:nchars)
1253  END SUBROUTINE print_func
1254 
1255 END MODULE grid_api
static void print_func(char *message, int output_unit)
Wrapper for printf, passed to dbm_library_print_stats.
Definition: dbm_miniapp.c:28
void grid_create_basis_set(const int nset, const int nsgf, const int maxco, const int maxpgf, const int lmin[nset], const int lmax[nset], const int npgf[nset], const int nsgf_set[nset], const int first_sgf[nset], const double sphi[nsgf][maxco], const double zet[nset][maxpgf], grid_basis_set **basis_set_out)
Allocates a basis set which can be passed to grid_create_task_list. See grid_task_list....
void grid_free_basis_set(grid_basis_set *basis_set)
Deallocates given basis set.
void apply_cutoff(void *ptr)
void grid_library_finalize(void)
Finalizes the grid library.
Definition: grid_library.c:83
void grid_library_print_stats(void(*mpi_sum_func)(long *, int), const int mpi_comm, void(*print_func)(char *, int), const int output_unit)
Prints statistics gathered by the grid library.
Definition: grid_library.c:155
void grid_library_init(void)
Initializes the grid library.
Definition: grid_library.c:49
void grid_library_set_config(const enum grid_backend backend, const bool validate, const bool apply_cutoff)
Configures the grid library.
Definition: grid_library.c:112
Fortran API for the grid package, which is written in C.
Definition: grid_api.F:12
integer, parameter, public grid_func_adbmdab_z
Definition: grid_api.F:33
integer, parameter, public grid_func_core_x
Definition: grid_api.F:62
integer, parameter, public grid_func_adbmdab_y
Definition: grid_api.F:32
integer, parameter, public grid_func_ardbmdarb_yx
Definition: grid_api.F:37
integer, parameter, public grid_func_dab_z
Definition: grid_api.F:57
subroutine, public grid_collocate_task_list(task_list, ga_gb_function, pab_blocks, rs_grids)
Collocate all tasks of in given list onto given grids.
Definition: grid_api.F:968
integer, parameter, public grid_func_dzdx
Definition: grid_api.F:51
integer, parameter, public grid_func_ardbmdarb_zz
Definition: grid_api.F:42
integer, parameter, public grid_backend_auto
Definition: grid_api.F:66
integer, parameter, public grid_backend_gpu
Definition: grid_api.F:70
subroutine, public grid_free_task_list(task_list)
Deallocates given task list, basis_sets have to be freed separately.
Definition: grid_api.F:935
integer, parameter, public grid_func_dzdz
Definition: grid_api.F:54
integer, parameter, public grid_func_dydz
Definition: grid_api.F:50
integer, parameter, public grid_func_adb_y
Definition: grid_api.F:59
integer, parameter, public grid_func_dxdy
Definition: grid_api.F:49
integer, parameter, public grid_func_dabpadb_y
Definition: grid_api.F:44
integer, parameter, public grid_func_ardbmdarb_xy
Definition: grid_api.F:35
integer, parameter, public grid_func_dab_y
Definition: grid_api.F:56
integer, parameter, public grid_backend_hip
Definition: grid_api.F:71
subroutine, public grid_create_task_list(ntasks, natoms, nkinds, nblocks, block_offsets, atom_positions, atom_kinds, basis_sets, level_list, iatom_list, jatom_list, iset_list, jset_list, ipgf_list, jpgf_list, border_mask_list, block_num_list, radius_list, rab_list, rs_grids, task_list)
Allocates a task list which can be passed to grid_collocate_task_list.
Definition: grid_api.F:726
integer, parameter, public grid_func_adb_z
Definition: grid_api.F:60
integer, parameter, public grid_func_ardbmdarb_zx
Definition: grid_api.F:40
integer, parameter, public grid_func_adb_x
Definition: grid_api.F:58
integer, parameter, public grid_func_dxdx
Definition: grid_api.F:52
integer, parameter, public grid_func_ardbmdarb_xx
Definition: grid_api.F:34
integer, parameter, public grid_func_dadb
Definition: grid_api.F:30
integer, parameter, public grid_backend_dgemm
Definition: grid_api.F:69
integer, parameter, public grid_func_dydy
Definition: grid_api.F:53
integer, parameter, public grid_func_dabpadb_z
Definition: grid_api.F:45
integer, parameter, public grid_backend_cpu
Definition: grid_api.F:68
integer, parameter, public grid_func_dabpadb_x
Definition: grid_api.F:43
integer, parameter, public grid_func_dx
Definition: grid_api.F:46
integer, parameter, public grid_func_dz
Definition: grid_api.F:48
integer, parameter, public grid_func_ardbmdarb_yz
Definition: grid_api.F:39
integer, parameter, public grid_func_ab
Definition: grid_api.F:29
subroutine, public integrate_pgf_product(la_max, zeta, la_min, lb_max, zetb, lb_min, ra, rab, rsgrid, hab, pab, o1, o2, radius, calculate_forces, force_a, force_b, compute_tau, use_virial, my_virial_a, my_virial_b, hdab, hadb, a_hdab, use_subpatch, subpatch_pattern)
low level function to compute matrix elements of primitive gaussian functions
Definition: grid_api.F:279
integer, parameter, public grid_func_ardbmdarb_yy
Definition: grid_api.F:38
subroutine, public grid_integrate_task_list(task_list, compute_tau, calculate_forces, calculate_virial, pab_blocks, rs_grids, hab_blocks, forces, virial)
Integrate all tasks of in given list from given grids.
Definition: grid_api.F:1040
integer, parameter, public grid_func_core_y
Definition: grid_api.F:63
integer, parameter, public grid_backend_ref
Definition: grid_api.F:67
integer, parameter, public grid_func_adbmdab_x
Definition: grid_api.F:31
integer, parameter, public grid_func_dab_x
Definition: grid_api.F:55
subroutine, public collocate_pgf_product(la_max, zeta, la_min, lb_max, zetb, lb_min, ra, rab, scale, pab, o1, o2, rsgrid, ga_gb_function, radius, use_subpatch, subpatch_pattern)
low level collocation of primitive gaussian functions
Definition: grid_api.F:119
integer, parameter, public grid_func_ardbmdarb_zy
Definition: grid_api.F:41
integer, parameter, public grid_func_core_z
Definition: grid_api.F:64
integer, parameter, public grid_func_dy
Definition: grid_api.F:47
integer, parameter, public grid_func_ardbmdarb_xz
Definition: grid_api.F:36
Defines the basic variable types.
Definition: kinds.F:23
integer, parameter, public dp
Definition: kinds.F:34
Interface to the message passing library MPI.
Fortran API for the offload package, which is written in C.
Definition: offload_api.F:12
Utilities for string manipulations.
integer function, public strlcpy_c2f(fstring, cstring)
Copy the content of a \0-terminated C-string to a finite-length Fortran string.