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