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