18 USE iso_c_binding,
ONLY: c_char,&
29#include "./base/base_uses.f90"
34 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'nnp_gpu'
38 INTEGER,
PARAMETER,
PRIVATE :: gpu_walk_init_max_n_neigh = 96
56#if (defined(__OFFLOAD) || defined(__OFFLOAD_CUDA) || defined(__OFFLOAD_HIP)) && !defined(__NO_OFFLOAD_NNP)
58 FUNCTION nnp_gpu_set_precision_c(use_fp32) &
59 result(rc)
BIND(C, NAME="nnp_gpu_set_precision")
60 USE iso_c_binding,
ONLY: c_int
61 INTEGER(KIND=c_int),
VALUE :: use_fp32
62 INTEGER(KIND=c_int) :: rc
64 END FUNCTION nnp_gpu_set_precision_c
68 FUNCTION nnp_gpu_register_env_c() &
69 result(n_live)
BIND(C, NAME="nnp_gpu_register_env")
70 USE iso_c_binding,
ONLY: c_int
71 INTEGER(KIND=c_int) :: n_live
73 END FUNCTION nnp_gpu_register_env_c
77 SUBROUTINE nnp_gpu_unregister_env_c() &
78 BIND(C, NAME="nnp_gpu_unregister_env")
79 END SUBROUTINE nnp_gpu_unregister_env_c
83 FUNCTION nnp_gpu_max_se_c() &
84 result(cap)
BIND(C, NAME="nnp_gpu_max_se_c")
85 USE iso_c_binding,
ONLY: c_int
86 INTEGER(KIND=c_int) :: cap
88 END FUNCTION nnp_gpu_max_se_c
90 FUNCTION nnp_gpu_spline_cache_max_c() &
91 result(cap)
BIND(C, NAME="nnp_gpu_spline_cache_max_c")
92 USE iso_c_binding,
ONLY: c_int
93 INTEGER(KIND=c_int) :: cap
95 END FUNCTION nnp_gpu_spline_cache_max_c
97 FUNCTION nnp_gpu_upload_positions_step_c(num_atoms, h_coord) &
98 result(rc)
BIND(C, NAME="nnp_gpu_upload_positions_step_c")
99 USE iso_c_binding,
ONLY: c_double, c_int
100 INTEGER(KIND=c_int),
VALUE :: num_atoms
101 REAL(KIND=c_double),
DIMENSION(*),
INTENT(IN) :: h_coord
102 INTEGER(KIND=c_int) :: rc
104 END FUNCTION nnp_gpu_upload_positions_step_c
106 FUNCTION nnp_gpu_upload_image_table_c(n_images, h_image_table) &
107 result(rc)
BIND(C, NAME="nnp_gpu_upload_image_table_c")
108 USE iso_c_binding,
ONLY: c_double, c_int
109 INTEGER(KIND=c_int),
VALUE :: n_images
110 REAL(KIND=c_double),
DIMENSION(*),
INTENT(IN) :: h_image_table
111 INTEGER(KIND=c_int) :: rc
113 END FUNCTION nnp_gpu_upload_image_table_c
115 FUNCTION nnp_gpu_upload_cell_list_c(n_images, n_cells, h_image_atom, &
116 h_image_shift, h_head, h_next) &
117 result(rc)
BIND(C, NAME="nnp_gpu_upload_cell_list_c")
118 USE iso_c_binding,
ONLY: c_int
119 INTEGER(KIND=c_int),
VALUE :: n_images, n_cells
120 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_image_atom, h_image_shift, h_head, &
122 INTEGER(KIND=c_int) :: rc
124 END FUNCTION nnp_gpu_upload_cell_list_c
126 FUNCTION nnp_gpu_upload_pair_map_c(n_ele, max_pair_grps, max_n_radgrp, &
127 max_n_anggrp, h_n_rad, h_n_ang1, h_n_ang2, &
128 h_pair_max_cutoff, h_rad_groups, h_ang1_groups, &
129 h_ang2_groups, h_rad_cutoff, h_ang_cutoff) &
130 result(rc)
BIND(C, NAME="nnp_gpu_upload_pair_map_c")
131 USE iso_c_binding,
ONLY: c_double, c_int
132 INTEGER(KIND=c_int),
VALUE :: n_ele, max_pair_grps, max_n_radgrp, &
134 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_n_rad, h_n_ang1, h_n_ang2
135 REAL(KIND=c_double),
DIMENSION(*),
INTENT(IN) :: h_pair_max_cutoff
136 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_rad_groups, h_ang1_groups, &
138 REAL(KIND=c_double),
DIMENSION(*),
INTENT(IN) :: h_rad_cutoff, h_ang_cutoff
139 INTEGER(KIND=c_int) :: rc
141 END FUNCTION nnp_gpu_upload_pair_map_c
143 FUNCTION nnp_gpu_cell_list_walk_c(num_atoms_global, n_ele, n_images, n_cells, &
144 n_atoms_in_e_max, max_n_neigh_rad, &
145 max_n_neigh_ang1, max_n_neigh_ang2, max_n_radgrp, &
146 max_n_anggrp, h_nbin, h_bin_lower, h_bin_width, &
147 h_bin_span, h_perd, h_exact_pbc_copies, &
148 h_coord_scaled, h_ele_ind_global, &
149 h_atoms_global_per_e, h_n_atoms_in_e) &
150 result(rc)
BIND(C, NAME="nnp_gpu_cell_list_walk_c")
151 USE iso_c_binding,
ONLY: c_double, c_int
152 INTEGER(KIND=c_int),
VALUE :: num_atoms_global, n_ele, n_images, n_cells, n_atoms_in_e_max, &
153 max_n_neigh_rad, max_n_neigh_ang1, max_n_neigh_ang2, max_n_radgrp, max_n_anggrp
154 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_nbin
155 REAL(KIND=c_double),
DIMENSION(*),
INTENT(IN) :: h_bin_lower, h_bin_width
156 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_bin_span, h_perd, h_exact_pbc_copies
157 REAL(KIND=c_double),
DIMENSION(*),
INTENT(IN) :: h_coord_scaled
158 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_ele_ind_global, h_atoms_global_per_e, &
160 INTEGER(KIND=c_int) :: rc
162 END FUNCTION nnp_gpu_cell_list_walk_c
164 FUNCTION nnp_gpu_walk_counts_d2h_c(n_atoms_in_e_max, max_n_radgrp, max_n_anggrp, &
165 n_ele, h_n_rad_pa, h_n_ang1_pa, h_n_ang2_pa) &
166 result(rc)
BIND(C, NAME="nnp_gpu_walk_counts_d2h_c")
167 USE iso_c_binding,
ONLY: c_int
168 INTEGER(KIND=c_int),
VALUE :: n_atoms_in_e_max, max_n_radgrp, &
170 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(INOUT) :: h_n_rad_pa, h_n_ang1_pa, h_n_ang2_pa
171 INTEGER(KIND=c_int) :: rc
173 END FUNCTION nnp_gpu_walk_counts_d2h_c
175 FUNCTION nnp_gpu_begin_descriptor_step_c(n_atoms, n_input_max) &
176 result(rc)
BIND(C, NAME="nnp_gpu_begin_descriptor_step")
177 USE iso_c_binding,
ONLY: c_int
178 INTEGER(KIND=c_int),
VALUE :: n_atoms, n_input_max
179 INTEGER(KIND=c_int) :: rc
181 END FUNCTION nnp_gpu_begin_descriptor_step_c
183 FUNCTION nnp_gpu_upload_scaling_tables_c(n_ele, n_input_max, h_loc_av, h_loc_min, &
184 h_loc_max, h_sigma, h_n_input_nodes) &
185 result(rc)
BIND(C, NAME="nnp_gpu_upload_scaling_tables_c")
186 USE iso_c_binding,
ONLY: c_double, c_int
187 INTEGER(KIND=c_int),
VALUE :: n_ele, n_input_max
188 REAL(KIND=c_double),
DIMENSION(*),
INTENT(IN) :: h_loc_av, h_loc_min, h_loc_max, h_sigma
189 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_n_input_nodes
190 INTEGER(KIND=c_int) :: rc
192 END FUNCTION nnp_gpu_upload_scaling_tables_c
194 FUNCTION nnp_gpu_upload_se_static_tables_c(n_ele, max_n_radgrp, max_n_anggrp, &
195 total_rad_symf, total_ang_symf, &
196 h_rad_packed, h_rad_offsets, &
197 h_ang_packed, h_ang_offsets) &
198 result(rc)
BIND(C, NAME="nnp_gpu_upload_se_static_tables_c")
199 USE iso_c_binding,
ONLY: c_int
200 INTEGER(KIND=c_int),
VALUE :: n_ele, max_n_radgrp, max_n_anggrp, &
201 total_rad_symf, total_ang_symf
202 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_rad_packed, h_rad_offsets, &
203 h_ang_packed, h_ang_offsets
204 INTEGER(KIND=c_int) :: rc
206 END FUNCTION nnp_gpu_upload_se_static_tables_c
208 FUNCTION nnp_gpu_scale_g_dev_c(n_atoms, n_input_max, n_ele, scaling_mode, &
209 scmin, scmax, h_ele_ind_for_atoms) &
210 result(rc)
BIND(C, NAME="nnp_gpu_scale_G_dev_c")
211 USE iso_c_binding,
ONLY: c_double, c_int
212 INTEGER(KIND=c_int),
VALUE :: n_atoms, n_input_max, n_ele, scaling_mode
213 REAL(KIND=c_double),
VALUE :: scmin, scmax
214 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_ele_ind_for_atoms
215 INTEGER(KIND=c_int) :: rc
217 END FUNCTION nnp_gpu_scale_g_dev_c
221 FUNCTION nnp_gpu_extrapolation_flag_c() &
222 result(flag)
BIND(C, NAME="nnp_gpu_extrapolation_flag_c")
223 USE iso_c_binding,
ONLY: c_int
224 INTEGER(KIND=c_int) :: flag
226 END FUNCTION nnp_gpu_extrapolation_flag_c
228 FUNCTION nnp_gpu_radial_sf_to_g_dev_c(n_atoms_in_e, max_n_neigh_per_se, n_symf, &
229 spline_n, spline_dx, spline_dx_inv, &
230 spline_x_max, h_spline_y, h_spline_dy, &
231 s_0based, e_0based, max_n_radgrp_walk, &
232 n_atoms_in_e_max_walk, max_n_neigh_walk, &
233 istart_1based, n_input_max, se_idx) &
234 result(rc)
BIND(C, NAME="nnp_gpu_radial_sf_to_G_dev_c")
235 USE iso_c_binding,
ONLY: c_double, c_int
236 INTEGER(KIND=c_int),
VALUE :: n_atoms_in_e, max_n_neigh_per_se, &
238 REAL(KIND=c_double),
VALUE :: spline_dx, spline_dx_inv, spline_x_max
239 REAL(KIND=c_double),
DIMENSION(*),
INTENT(IN) :: h_spline_y, h_spline_dy
240 INTEGER(KIND=c_int),
VALUE :: s_0based, e_0based, max_n_radgrp_walk, n_atoms_in_e_max_walk, &
241 max_n_neigh_walk, istart_1based, n_input_max, se_idx
242 INTEGER(KIND=c_int) :: rc
244 END FUNCTION nnp_gpu_radial_sf_to_g_dev_c
246 FUNCTION nnp_gpu_angular_sf_to_g_dev_c(homo, cut_type, max_n_ang1_per_se, &
247 max_n_ang2_per_se, max_n_kk_per_se, n_symf, &
248 n_atoms_in_e, cutoff_s, cutoff_sqr, &
249 h_pack_lam, h_pack_zeta, h_pack_eta, &
250 h_pack_prefzeta, h_pack_izeta, &
251 h_pack_use_int_zeta, s_0based, e_0based, &
252 max_n_anggrp_walk, n_atoms_in_e_max_walk, &
253 max_n_neigh_ang1_walk, max_n_neigh_ang2_walk, &
254 istart_1based, n_rad_for_e, n_input_max, se_idx) &
255 result(rc)
BIND(C, NAME="nnp_gpu_angular_sf_to_G_dev_c")
256 USE iso_c_binding,
ONLY: c_char, c_double, c_int
257 INTEGER(KIND=c_int),
VALUE :: homo, cut_type, max_n_ang1_per_se, &
258 max_n_ang2_per_se, max_n_kk_per_se, &
260 REAL(KIND=c_double),
VALUE :: cutoff_s, cutoff_sqr
261 REAL(KIND=c_double),
DIMENSION(*),
INTENT(IN) :: h_pack_lam, h_pack_zeta, h_pack_eta, &
263 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_pack_izeta
264 CHARACTER(KIND=c_char),
DIMENSION(*),
INTENT(IN) :: h_pack_use_int_zeta
265 INTEGER(KIND=c_int),
VALUE :: s_0based, e_0based, max_n_anggrp_walk, n_atoms_in_e_max_walk, &
266 max_n_neigh_ang1_walk, max_n_neigh_ang2_walk, istart_1based, n_rad_for_e, n_input_max, &
268 INTEGER(KIND=c_int) :: rc
270 END FUNCTION nnp_gpu_angular_sf_to_g_dev_c
272 FUNCTION nnp_gpu_upload_nn_packed_c(n_committee, n_layer, max_n_nodes, n_ele, &
273 h_n_nodes, h_act_fnct, h_atom_energies, &
274 h_W_packed, h_b_packed) &
275 result(rc)
BIND(C, NAME="nnp_gpu_upload_nn_packed_c")
276 USE iso_c_binding,
ONLY: c_double, c_int
277 INTEGER(KIND=c_int),
VALUE :: n_committee, n_layer, max_n_nodes, n_ele
278 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_n_nodes, h_act_fnct
279 REAL(KIND=c_double),
DIMENSION(*),
INTENT(IN) :: h_atom_energies, h_w_packed, h_b_packed
280 INTEGER(KIND=c_int) :: rc
282 END FUNCTION nnp_gpu_upload_nn_packed_c
284 FUNCTION nnp_gpu_nn_atomwise_with_g_dev_c(n_atoms, n_committee, n_layer, max_n_nodes, &
285 n_input_max, normnodes, n_ele, h_ele_ind, &
286 h_atomic_energy, h_dE_dG) &
287 result(rc)
BIND(C, NAME="nnp_gpu_nn_atomwise_with_G_dev_c")
288 USE iso_c_binding,
ONLY: c_double, c_int, c_ptr
289 INTEGER(KIND=c_int),
VALUE :: n_atoms, n_committee, n_layer, &
290 max_n_nodes, n_input_max, normnodes, &
292 INTEGER(KIND=c_int),
DIMENSION(*),
INTENT(IN) :: h_ele_ind
293 REAL(KIND=c_double),
DIMENSION(*),
INTENT(INOUT) :: h_atomic_energy
294 TYPE(c_ptr),
VALUE :: h_dE_dG
295 INTEGER(KIND=c_int) :: rc
300 END FUNCTION nnp_gpu_nn_atomwise_with_g_dev_c
302 FUNCTION nnp_gpu_force_scatter_begin_c(num_atoms_global, n_committee, h_force) &
303 result(rc)
BIND(C, NAME="nnp_gpu_force_scatter_begin_c")
304 USE iso_c_binding,
ONLY: c_double, c_int
305 INTEGER(KIND=c_int),
VALUE :: num_atoms_global, n_committee
306 REAL(KIND=c_double),
DIMENSION(*),
INTENT(IN) :: h_force
307 INTEGER(KIND=c_int) :: rc
309 END FUNCTION nnp_gpu_force_scatter_begin_c
311 FUNCTION nnp_gpu_force_scatter_end_c(num_atoms_global, n_committee, h_force) &
312 result(rc)
BIND(C, NAME="nnp_gpu_force_scatter_end_c")
313 USE iso_c_binding,
ONLY: c_double, c_int
314 INTEGER(KIND=c_int),
VALUE :: num_atoms_global, n_committee
315 REAL(KIND=c_double),
DIMENSION(*),
INTENT(INOUT) :: h_force
316 INTEGER(KIND=c_int) :: rc
318 END FUNCTION nnp_gpu_force_scatter_end_c
323 FUNCTION nnp_gpu_force_scatter_virial_d2h_c(n_committee, h_virial) &
324 result(rc)
BIND(C, NAME="nnp_gpu_force_scatter_virial_d2h_c")
325 USE iso_c_binding,
ONLY: c_double, c_int
326 INTEGER(KIND=c_int),
VALUE :: n_committee
327 REAL(KIND=c_double),
DIMENSION(*),
INTENT(INOUT) :: h_virial
328 INTEGER(KIND=c_int) :: rc
330 END FUNCTION nnp_gpu_force_scatter_virial_d2h_c
332 FUNCTION nnp_gpu_force_scatter_radial_c(n_atoms_in_e, n_symf, max_n_neigh_per_se, &
333 n_committee, n_input_max, num_atoms_global, &
334 ele_idx, scaling_mode, scmin, scmax, s_0based, &
335 max_n_radgrp_walk, n_atoms_in_e_max_walk, &
336 max_n_neigh_walk, istart_1based, se_idx, &
338 result(rc)
BIND(C, NAME="nnp_gpu_force_scatter_radial_c")
339 USE iso_c_binding,
ONLY: c_double, c_int
340 INTEGER(KIND=c_int),
VALUE :: n_atoms_in_e, n_symf, &
341 max_n_neigh_per_se, n_committee, &
342 n_input_max, num_atoms_global, &
343 ele_idx, scaling_mode
344 REAL(KIND=c_double),
VALUE :: scmin, scmax
345 INTEGER(KIND=c_int),
VALUE :: s_0based, max_n_radgrp_walk, n_atoms_in_e_max_walk, &
346 max_n_neigh_walk, istart_1based, se_idx, accumulate_virial
347 INTEGER(KIND=c_int) :: rc
349 END FUNCTION nnp_gpu_force_scatter_radial_c
351 FUNCTION nnp_gpu_force_scatter_angular_c(n_atoms_in_e, n_symf, max_n_ang1_per_se, &
352 max_n_kk_per_se, n_committee, n_input_max, &
353 num_atoms_global, ele_idx, n_rad_offset, &
354 scaling_mode, homo, scmin, scmax, s_0based, &
355 max_n_anggrp_walk, n_atoms_in_e_max_walk, &
356 max_n_neigh_ang1_walk, max_n_neigh_ang2_walk, &
357 istart_1based, se_idx, accumulate_virial) &
358 result(rc)
BIND(C, NAME="nnp_gpu_force_scatter_angular_c")
359 USE iso_c_binding,
ONLY: c_double, c_int
360 INTEGER(KIND=c_int),
VALUE :: n_atoms_in_e, n_symf, max_n_ang1_per_se, max_n_kk_per_se, &
361 n_committee, n_input_max, num_atoms_global, ele_idx, n_rad_offset, scaling_mode, homo
362 REAL(KIND=c_double),
VALUE :: scmin, scmax
363 INTEGER(KIND=c_int),
VALUE :: s_0based, max_n_anggrp_walk, n_atoms_in_e_max_walk, &
364 max_n_neigh_ang1_walk, max_n_neigh_ang2_walk, istart_1based, se_idx, accumulate_virial
365 INTEGER(KIND=c_int) :: rc
367 END FUNCTION nnp_gpu_force_scatter_angular_c
383#if (defined(__OFFLOAD) || defined(__OFFLOAD_CUDA) || defined(__OFFLOAD_HIP)) && !defined(__NO_OFFLOAD_NNP)
407 INTEGER,
INTENT(IN) :: gpu_precision
408 LOGICAL,
INTENT(OUT) :: accepted
412#if (defined(__OFFLOAD) || defined(__OFFLOAD_CUDA) || defined(__OFFLOAD_HIP)) && !defined(__NO_OFFLOAD_NNP)
413 CHARACTER(len=*),
PARAMETER :: routinen =
'nnp_gpu_init_device'
416 CALL timeset(routinen, handle)
428 IF (nnp_gpu_register_env_c() > 1)
THEN
429 CALL nnp_gpu_unregister_env_c()
431 CALL timestop(handle)
438 cpabort(
"NNP GPU init failed: cannot push the precision selector to the device.")
441 CALL timestop(handle)
443 mark_used(gpu_precision)
446 cpabort(
"NNP GPU support is not compiled into this binary.")
464 TYPE(
nnp_type),
INTENT(IN),
POINTER :: nnp
465 CHARACTER(LEN=*),
INTENT(OUT) :: reason
468#if (defined(__OFFLOAD) || defined(__OFFLOAD_CUDA) || defined(__OFFLOAD_HIP)) && !defined(__NO_OFFLOAD_NNP)
469 INTEGER :: cache_needed, e, mag, mrg, se_cap
474 CALL nnp_gpu_max_symfgrp(nnp, mrg, mag)
475 se_cap = nnp_gpu_max_se_c()
476 IF (mrg*nnp%n_ele > se_cap .OR. mag*nnp%n_ele > se_cap)
THEN
478 WRITE (reason,
'(A,I0,A,I0)')
"the model needs ", &
479 max(mrg*nnp%n_ele, mag*nnp%n_ele), &
480 " (group, element) device slots per kind and this build holds "// &
481 "NNP_MAX_SE = ", se_cap
487 cache_needed = cache_needed + 2*nnp%rad(e)%n_symfgrp + 4*nnp%ang(e)%n_symfgrp
489 IF (cache_needed > nnp_gpu_spline_cache_max_c())
THEN
491 WRITE (reason,
'(A,I0,A,I0)')
"the model needs ", cache_needed, &
492 " device parameter-cache entries and this build holds "// &
493 "NNP_SPLINE_CACHE_MAX = ", nnp_gpu_spline_cache_max_c()
515 SUBROUTINE nnp_gpu_max_symfgrp(nnp, max_rad, max_ang)
516 TYPE(
nnp_type),
INTENT(IN),
POINTER :: nnp
517 INTEGER,
INTENT(OUT) :: max_rad, max_ang
524 max_rad = max(max_rad, nnp%rad(e)%n_symfgrp)
525 max_ang = max(max_ang, nnp%ang(e)%n_symfgrp)
528 END SUBROUTINE nnp_gpu_max_symfgrp
542 SUBROUTINE nnp_gpu_run_walk(nnp, istart, mecalc)
543 TYPE(
nnp_type),
INTENT(INOUT),
POINTER :: nnp
544 INTEGER,
INTENT(IN) :: istart, mecalc
548#if (defined(__OFFLOAD) || defined(__OFFLOAD_CUDA) || defined(__OFFLOAD_HIP)) && !defined(__NO_OFFLOAD_NNP)
549 CHARACTER(len=*),
PARAMETER :: routinen =
'nnp_gpu_run_walk'
550 INTEGER :: attempts, e_w, ec, gg, ie, ii, je, mag, mpg, mrg, n_atoms_in_e_max, ne, &
551 pflat, rc_walk, slot_w, ss
552 INTEGER(KIND=c_int),
DIMENSION(3) :: epbc_buf, nbin_buf, perd_buf, span_buf
553 REAL(kind=
dp),
DIMENSION(3) :: lower_buf, width_buf
554 INTEGER(KIND=c_int),
ALLOCATABLE,
DIMENSION(:) :: atoms_global_per_e_buf, &
555 ele_ind_global_buf, n_atoms_in_e_buf, &
556 pm_ang1_g, pm_ang2_g, pm_n_ang1, &
557 pm_n_ang2, pm_n_rad, pm_rad_g
558 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: pm_ang_cut, pm_max_cut, pm_rad_cut
560 CALL timeset(routinen, handle)
562 IF (.NOT.
ALLOCATED(nnp%gpu_host_state))
ALLOCATE (nnp%gpu_host_state)
565 CALL nnp_gpu_max_symfgrp(nnp, mrg, mag)
572 ec = nnp_gpu_upload_positions_step_c(int(nnp%num_atoms, c_int), &
573 nnp%cell_list_cache%coord_primary)
574 IF (ec /= 0) cpabort(
"NNP GPU: position upload failed.")
576 IF (nnp%cell_list_cache%n_images > 0)
THEN
577 IF (nnp%gpu_host_state%image_table_generation /= &
578 nnp%cell_list_cache%rebuild_count)
THEN
579 ec = nnp_gpu_upload_image_table_c(int(nnp%cell_list_cache%n_images, c_int), &
580 nnp%cell_list_cache%image_translation)
581 IF (ec /= 0) cpabort(
"NNP GPU: image-table upload failed.")
582 nnp%gpu_host_state%image_table_generation = nnp%cell_list_cache%rebuild_count
584 IF (nnp%cell_list_cache%n_cells > 0)
THEN
585 ec = nnp_gpu_upload_cell_list_c(int(nnp%cell_list_cache%n_images, c_int), &
586 int(nnp%cell_list_cache%n_cells, c_int), &
587 int(nnp%cell_list_cache%image_atom, c_int), &
588 int(nnp%cell_list_cache%image_shift, c_int), &
589 int(nnp%cell_list_cache%head, c_int), &
590 int(nnp%cell_list_cache%next, c_int))
591 IF (ec /= 0) cpabort(
"NNP GPU: cell-list upload failed.")
602 mpg = max(mpg, nnp%neighbor_interface_state%pair_map(ie, je)%n_rad, &
603 nnp%neighbor_interface_state%pair_map(ie, je)%n_ang1, &
604 nnp%neighbor_interface_state%pair_map(ie, je)%n_ang2)
607 ALLOCATE (pm_n_rad(ne*ne), pm_n_ang1(ne*ne), pm_n_ang2(ne*ne), pm_max_cut(ne*ne))
608 ALLOCATE (pm_rad_g(mpg*ne*ne), pm_ang1_g(mpg*ne*ne), pm_ang2_g(mpg*ne*ne))
609 ALLOCATE (pm_rad_cut(mrg*ne), pm_ang_cut(mag*ne))
613 pm_rad_cut(:) = 0.0_dp
614 pm_ang_cut(:) = 0.0_dp
617 pflat = (ie - 1) + ne*(je - 1)
618 associate(pmap => nnp%neighbor_interface_state%pair_map(ie, je))
619 pm_n_rad(pflat + 1) = int(pmap%n_rad, c_int)
620 pm_n_ang1(pflat + 1) = int(pmap%n_ang1, c_int)
621 pm_n_ang2(pflat + 1) = int(pmap%n_ang2, c_int)
622 pm_max_cut(pflat + 1) = pmap%max_relevant_cutoff
623 DO gg = 1, pmap%n_rad
624 pm_rad_g((gg - 1) + mpg*pflat + 1) = int(pmap%rad_groups(gg), c_int)
626 DO gg = 1, pmap%n_ang1
627 pm_ang1_g((gg - 1) + mpg*pflat + 1) = int(pmap%ang1_groups(gg), c_int)
629 DO gg = 1, pmap%n_ang2
630 pm_ang2_g((gg - 1) + mpg*pflat + 1) = int(pmap%ang2_groups(gg), c_int)
636 DO ss = 1, nnp%rad(ie)%n_symfgrp
637 pm_rad_cut((ss - 1) + mrg*(ie - 1) + 1) = nnp%rad(ie)%symfgrp(ss)%cutoff
639 DO ss = 1, nnp%ang(ie)%n_symfgrp
640 pm_ang_cut((ss - 1) + mag*(ie - 1) + 1) = nnp%ang(ie)%symfgrp(ss)%cutoff
643 ec = nnp_gpu_upload_pair_map_c(int(ne, c_int), int(mpg, c_int), int(mrg, c_int), &
644 int(mag, c_int), pm_n_rad, pm_n_ang1, pm_n_ang2, &
645 pm_max_cut, pm_rad_g, pm_ang1_g, pm_ang2_g, &
646 pm_rad_cut, pm_ang_cut)
647 IF (ec /= 0) cpabort(
"NNP GPU: pair-map upload failed.")
651 ALLOCATE (n_atoms_in_e_buf(ne))
652 n_atoms_in_e_buf(:) = 0
653 DO ii = istart, istart + mecalc - 1
654 e_w = nnp%ele_ind(ii)
655 n_atoms_in_e_buf(e_w) = n_atoms_in_e_buf(e_w) + 1
657 n_atoms_in_e_max = maxval(n_atoms_in_e_buf)
663 nnp%gpu_host_state%n_atoms_in_e_max = n_atoms_in_e_max
664 IF (
ALLOCATED(nnp%gpu_host_state%n_atoms_in_e))
THEN
665 DEALLOCATE (nnp%gpu_host_state%n_atoms_in_e)
667 ALLOCATE (nnp%gpu_host_state%n_atoms_in_e(ne))
668 nnp%gpu_host_state%n_atoms_in_e(:) = n_atoms_in_e_buf(:)
670 IF (n_atoms_in_e_max <= 0)
THEN
671 DEALLOCATE (n_atoms_in_e_buf, pm_n_rad, pm_n_ang1, pm_n_ang2, pm_max_cut, &
672 pm_rad_g, pm_ang1_g, pm_ang2_g, pm_rad_cut, pm_ang_cut)
673 CALL timestop(handle)
676 ALLOCATE (atoms_global_per_e_buf(n_atoms_in_e_max*ne))
677 atoms_global_per_e_buf(:) = 0
678 n_atoms_in_e_buf(:) = 0
679 DO ii = istart, istart + mecalc - 1
680 e_w = nnp%ele_ind(ii)
681 n_atoms_in_e_buf(e_w) = n_atoms_in_e_buf(e_w) + 1
682 slot_w = n_atoms_in_e_buf(e_w)
683 atoms_global_per_e_buf((slot_w - 1) + n_atoms_in_e_max*(e_w - 1) + 1) = int(ii, c_int)
685 ALLOCATE (ele_ind_global_buf(nnp%num_atoms))
686 DO ii = 1, nnp%num_atoms
687 ele_ind_global_buf(ii) = int(nnp%ele_ind(ii), c_int)
690 nbin_buf = int(nnp%cell_list_cache%nbin, c_int)
691 span_buf = int(nnp%cell_list_cache%bin_span, c_int)
692 perd_buf = int(nnp%cell_list_cache%perd, c_int)
693 epbc_buf = int(nnp%cell_list_cache%exact_pbc_copies, c_int)
694 lower_buf = nnp%cell_list_cache%lower
695 width_buf = nnp%cell_list_cache%bin_width
697 IF (.NOT. nnp%gpu_host_state%walk_initialised)
THEN
698 nnp%gpu_host_state%max_n_neigh_rad = gpu_walk_init_max_n_neigh
699 nnp%gpu_host_state%max_n_neigh_ang1 = gpu_walk_init_max_n_neigh
700 nnp%gpu_host_state%max_n_neigh_ang2 = gpu_walk_init_max_n_neigh
701 nnp%gpu_host_state%walk_initialised = .true.
706 attempts = attempts + 1
707 rc_walk = nnp_gpu_cell_list_walk_c(int(nnp%num_atoms, c_int), int(ne, c_int), &
708 int(nnp%cell_list_cache%n_images, c_int), &
709 int(nnp%cell_list_cache%n_cells, c_int), &
710 int(n_atoms_in_e_max, c_int), &
711 int(nnp%gpu_host_state%max_n_neigh_rad, c_int), &
712 int(nnp%gpu_host_state%max_n_neigh_ang1, c_int), &
713 int(nnp%gpu_host_state%max_n_neigh_ang2, c_int), &
714 int(mrg, c_int), int(mag, c_int), nbin_buf, &
715 lower_buf, width_buf, span_buf, perd_buf, epbc_buf, &
716 nnp%cell_list_cache%coord_scaled, ele_ind_global_buf, &
717 atoms_global_per_e_buf, n_atoms_in_e_buf)
718 IF (rc_walk == 0)
EXIT
719 IF (rc_walk == -2 .AND. attempts < 4)
THEN
720 nnp%gpu_host_state%max_n_neigh_rad = nnp%gpu_host_state%max_n_neigh_rad*2
721 nnp%gpu_host_state%max_n_neigh_ang1 = nnp%gpu_host_state%max_n_neigh_ang1*2
722 nnp%gpu_host_state%max_n_neigh_ang2 = nnp%gpu_host_state%max_n_neigh_ang2*2
725 IF (rc_walk == -2)
THEN
726 cpabort(
"NNP GPU: a per-atom neighbour list still overflows after three width doublings.")
728 cpabort(
"NNP GPU: cell-list walk failed.")
733 IF (
ALLOCATED(nnp%gpu_host_state%n_rad_pa))
DEALLOCATE (nnp%gpu_host_state%n_rad_pa)
734 IF (
ALLOCATED(nnp%gpu_host_state%n_ang1_pa))
DEALLOCATE (nnp%gpu_host_state%n_ang1_pa)
735 IF (
ALLOCATED(nnp%gpu_host_state%n_ang2_pa))
DEALLOCATE (nnp%gpu_host_state%n_ang2_pa)
736 ALLOCATE (nnp%gpu_host_state%n_rad_pa(n_atoms_in_e_max, mrg, ne))
737 ALLOCATE (nnp%gpu_host_state%n_ang1_pa(n_atoms_in_e_max, mag, ne))
738 ALLOCATE (nnp%gpu_host_state%n_ang2_pa(n_atoms_in_e_max, mag, ne))
739 nnp%gpu_host_state%n_rad_pa(:, :, :) = 0
740 nnp%gpu_host_state%n_ang1_pa(:, :, :) = 0
741 nnp%gpu_host_state%n_ang2_pa(:, :, :) = 0
742 ec = nnp_gpu_walk_counts_d2h_c(int(n_atoms_in_e_max, c_int), int(mrg, c_int), &
743 int(mag, c_int), int(ne, c_int), &
744 nnp%gpu_host_state%n_rad_pa, nnp%gpu_host_state%n_ang1_pa, &
745 nnp%gpu_host_state%n_ang2_pa)
746 IF (ec /= 0) cpabort(
"NNP GPU: walk-count read-back failed.")
748 DEALLOCATE (n_atoms_in_e_buf, atoms_global_per_e_buf, ele_ind_global_buf, &
749 pm_n_rad, pm_n_ang1, pm_n_ang2, pm_max_cut, pm_rad_g, pm_ang1_g, pm_ang2_g, &
750 pm_rad_cut, pm_ang_cut)
752 CALL timestop(handle)
758 cpabort(
"NNP GPU support is not compiled into this binary.")
761 END SUBROUTINE nnp_gpu_run_walk
774 TYPE(nnp_type),
INTENT(IN),
POINTER :: nnp
778#if (defined(__OFFLOAD) || defined(__OFFLOAD_CUDA) || defined(__OFFLOAD_HIP)) && !defined(__NO_OFFLOAD_NNP)
779 CHARACTER(len=*),
PARAMETER :: routinen =
'nnp_gpu_upload_descriptor_statics'
780 INTEGER :: e, ec, m, max_n_anggrp, max_n_radgrp, n_ang_se_total, n_input_max, &
781 n_rad_se_total, n_symf_g, s, se_flat, se_off, sf, total_ang_symf, total_rad_symf
782 INTEGER(KIND=c_int),
ALLOCATABLE,
DIMENSION(:) :: ang_offsets, ang_packed, n_in_buf, &
783 rad_offsets, rad_packed
784 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:) :: loc_av_buf, loc_max_buf, loc_min_buf, &
787 CALL timeset(routinen, handle)
789 associate(n_ele => nnp%n_ele)
797 n_input_max = max(n_input_max, nnp%arc(e)%n_nodes(1))
800 ALLOCATE (loc_av_buf(n_ele*n_input_max))
801 ALLOCATE (loc_min_buf(n_ele*n_input_max))
802 ALLOCATE (loc_max_buf(n_ele*n_input_max))
803 ALLOCATE (sigma_buf(n_ele*n_input_max))
804 ALLOCATE (n_in_buf(n_ele))
811 n_in_buf(e) = int(nnp%arc(e)%n_nodes(1), c_int)
812 DO m = 1, nnp%n_rad(e)
813 loc_av_buf((e - 1)*n_input_max + m) = nnp%rad(e)%loc_av(m)
814 loc_min_buf((e - 1)*n_input_max + m) = nnp%rad(e)%loc_min(m)
815 loc_max_buf((e - 1)*n_input_max + m) = nnp%rad(e)%loc_max(m)
816 sigma_buf((e - 1)*n_input_max + m) = nnp%rad(e)%sigma(m)
818 DO m = 1, nnp%n_ang(e)
819 loc_av_buf((e - 1)*n_input_max + nnp%n_rad(e) + m) = nnp%ang(e)%loc_av(m)
820 loc_min_buf((e - 1)*n_input_max + nnp%n_rad(e) + m) = nnp%ang(e)%loc_min(m)
821 loc_max_buf((e - 1)*n_input_max + nnp%n_rad(e) + m) = nnp%ang(e)%loc_max(m)
822 sigma_buf((e - 1)*n_input_max + nnp%n_rad(e) + m) = nnp%ang(e)%sigma(m)
826 ec = nnp_gpu_upload_scaling_tables_c(int(n_ele, c_int), int(n_input_max, c_int), &
827 loc_av_buf, loc_min_buf, loc_max_buf, sigma_buf, &
829 IF (ec /= 0) cpabort(
"NNP GPU: descriptor scaling-table upload failed.")
831 DEALLOCATE (loc_av_buf, loc_min_buf, loc_max_buf, sigma_buf, n_in_buf)
837 CALL nnp_gpu_max_symfgrp(nnp, max_n_radgrp, max_n_anggrp)
839 n_rad_se_total = max_n_radgrp*n_ele
840 n_ang_se_total = max_n_anggrp*n_ele
844 DO s = 1, nnp%rad(e)%n_symfgrp
845 total_rad_symf = total_rad_symf + nnp%rad(e)%symfgrp(s)%n_symf
850 DO s = 1, nnp%ang(e)%n_symfgrp
851 total_ang_symf = total_ang_symf + nnp%ang(e)%symfgrp(s)%n_symf
855 ALLOCATE (rad_offsets(max(1, n_rad_se_total + 1)))
856 ALLOCATE (ang_offsets(max(1, n_ang_se_total + 1)))
857 ALLOCATE (rad_packed(max(1, total_rad_symf)))
858 ALLOCATE (ang_packed(max(1, total_ang_symf)))
859 rad_offsets = 0_c_int
860 ang_offsets = 0_c_int
866 DO s = 1, max_n_radgrp
867 se_flat = (s - 1) + max_n_radgrp*(e - 1)
868 rad_offsets(se_flat + 1) = int(se_off, c_int)
869 IF (s <= nnp%rad(e)%n_symfgrp)
THEN
870 n_symf_g = nnp%rad(e)%symfgrp(s)%n_symf
872 rad_packed(se_off + sf) = int(nnp%rad(e)%symfgrp(s)%symf(sf), c_int)
874 se_off = se_off + n_symf_g
878 IF (n_rad_se_total > 0) rad_offsets(n_rad_se_total + 1) = int(se_off, c_int)
882 DO s = 1, max_n_anggrp
883 se_flat = (s - 1) + max_n_anggrp*(e - 1)
884 ang_offsets(se_flat + 1) = int(se_off, c_int)
885 IF (s <= nnp%ang(e)%n_symfgrp)
THEN
886 n_symf_g = nnp%ang(e)%symfgrp(s)%n_symf
888 ang_packed(se_off + sf) = int(nnp%ang(e)%symfgrp(s)%symf(sf), c_int)
890 se_off = se_off + n_symf_g
894 IF (n_ang_se_total > 0) ang_offsets(n_ang_se_total + 1) = int(se_off, c_int)
896 ec = nnp_gpu_upload_se_static_tables_c(int(n_ele, c_int), int(max_n_radgrp, c_int), &
897 int(max_n_anggrp, c_int), &
898 int(total_rad_symf, c_int), &
899 int(total_ang_symf, c_int), &
900 rad_packed, rad_offsets, ang_packed, ang_offsets)
901 IF (ec /= 0) cpabort(
"NNP GPU: descriptor symf-map upload failed.")
903 DEALLOCATE (rad_packed, rad_offsets, ang_packed, ang_offsets)
907 CALL timestop(handle)
911 cpabort(
"NNP GPU support is not compiled into this binary.")
931 SUBROUTINE nnp_gpu_build_descriptor(nnp, istart, mecalc, n_input_max)
932 TYPE(nnp_type),
INTENT(INOUT),
POINTER :: nnp
933 INTEGER,
INTENT(IN) :: istart, mecalc, n_input_max
937#if (defined(__OFFLOAD) || defined(__OFFLOAD_CUDA) || defined(__OFFLOAD_HIP)) && !defined(__NO_OFFLOAD_NNP)
938 CHARACTER(len=*),
PARAMETER :: routinen =
'nnp_gpu_build_descriptor'
939 INTEGER :: cut_int, e, ec, i, i_local, max_n_ang1, max_n_ang2, max_n_anggrp, max_n_kk, &
940 max_n_neigh, max_n_radgrp, n_atoms_e, s, scaling_mode
941 LOGICAL :: homo, splines_ready
942 REAL(kind=dp) :: cutoff_s, cutoff_sqr
943 INTEGER(KIND=c_int),
ALLOCATABLE,
DIMENSION(:) :: ele_ind_buf, izeta_buf
944 CHARACTER(KIND=c_char),
ALLOCATABLE,
DIMENSION(:) :: use_int_zeta_buf
946 CALL timeset(routinen, handle)
950 CALL nnp_gpu_max_symfgrp(nnp, max_n_radgrp, max_n_anggrp)
953 ec = nnp_gpu_begin_descriptor_step_c(int(mecalc, c_int), int(n_input_max, c_int))
954 IF (ec /= 0) cpabort(
"NNP GPU: descriptor-step begin failed.")
959 splines_ready = .true.
961 DO s = 1, nnp%rad(e)%n_symfgrp
962 IF (.NOT. nnp%rad(e)%symfgrp(s)%spline_built) splines_ready = .false.
965 IF (.NOT. splines_ready)
CALL nnp_build_radial_splines(nnp)
967 associate(hstate => nnp%gpu_host_state)
972 n_atoms_e = hstate%n_atoms_in_e(e)
973 IF (n_atoms_e <= 0) cycle
974 DO s = 1, nnp%rad(e)%n_symfgrp
975 associate(symfgrp => nnp%rad(e)%symfgrp(s))
976 max_n_neigh = maxval(hstate%n_rad_pa(1:n_atoms_e, s, e))
977 IF (max_n_neigh <= 0) cycle
978 ec = nnp_gpu_radial_sf_to_g_dev_c( &
979 int(n_atoms_e, c_int), int(max_n_neigh, c_int), &
980 int(symfgrp%n_symf, c_int), int(symfgrp%spline_n, c_int), &
981 REAL(symfgrp%spline_dx, c_double), &
982 REAL(symfgrp%spline_dx_inv, c_double), &
983 REAL(symfgrp%spline_x_max, c_double), &
984 symfgrp%spline_y, symfgrp%spline_dy, &
985 int(s - 1, c_int), int(e - 1, c_int), int(max_n_radgrp, c_int), &
986 int(hstate%n_atoms_in_e_max, c_int), &
987 int(hstate%max_n_neigh_rad, c_int), int(istart, c_int), &
988 int(n_input_max, c_int), int((s - 1) + max_n_radgrp*(e - 1), c_int))
989 IF (ec /= 0) cpabort(
"NNP GPU: radial descriptor kernel failed.")
999 cut_int = nnp%cut_type - 1
1001 n_atoms_e = hstate%n_atoms_in_e(e)
1002 IF (n_atoms_e <= 0) cycle
1003 DO s = 1, nnp%ang(e)%n_symfgrp
1004 associate(symfgrp => nnp%ang(e)%symfgrp(s))
1005 homo = (symfgrp%ele(1) == symfgrp%ele(2))
1006 cutoff_s = symfgrp%cutoff
1007 cutoff_sqr = cutoff_s*cutoff_s
1009 max_n_ang1 = maxval(hstate%n_ang1_pa(1:n_atoms_e, s, e))
1010 IF (max_n_ang1 <= 0) cycle
1013 max_n_kk = max(1, max_n_ang1)
1015 max_n_ang2 = maxval(hstate%n_ang2_pa(1:n_atoms_e, s, e))
1025 IF (max_n_ang2 <= 0) cycle
1026 max_n_kk = max(1, max_n_ang2)
1029 ALLOCATE (izeta_buf(symfgrp%n_symf))
1030 ALLOCATE (use_int_zeta_buf(symfgrp%n_symf))
1031 DO i = 1, symfgrp%n_symf
1032 izeta_buf(i) = int(symfgrp%pack_izeta(i), c_int)
1033 use_int_zeta_buf(i) = merge(achar(1), achar(0), symfgrp%pack_use_int_zeta(i))
1036 ec = nnp_gpu_angular_sf_to_g_dev_c( &
1037 int(merge(1, 0, homo), c_int), int(cut_int, c_int), &
1038 int(max(1, max_n_ang1), c_int), int(max_n_ang2, c_int), &
1039 int(max_n_kk, c_int), int(symfgrp%n_symf, c_int), &
1040 int(n_atoms_e, c_int), real(cutoff_s, c_double), &
1041 REAL(cutoff_sqr, c_double), &
1042 symfgrp%pack_lam, symfgrp%pack_zeta, symfgrp%pack_eta, &
1043 symfgrp%pack_prefzeta, izeta_buf, use_int_zeta_buf, &
1044 int(s - 1, c_int), int(e - 1, c_int), int(max_n_anggrp, c_int), &
1045 int(hstate%n_atoms_in_e_max, c_int), &
1046 int(hstate%max_n_neigh_ang1, c_int), &
1047 int(hstate%max_n_neigh_ang2, c_int), int(istart, c_int), &
1048 int(nnp%n_rad(e), c_int), int(n_input_max, c_int), &
1049 int((s - 1) + max_n_anggrp*(e - 1), c_int))
1050 IF (ec /= 0) cpabort(
"NNP GPU: angular descriptor kernel failed.")
1052 DEALLOCATE (izeta_buf, use_int_zeta_buf)
1063 IF (nnp%scale_sigma_acsf)
THEN
1065 ELSE IF (nnp%center_acsf .AND. nnp%scale_acsf)
THEN
1067 ELSE IF (nnp%center_acsf)
THEN
1069 ELSE IF (nnp%scale_acsf)
THEN
1075 ALLOCATE (ele_ind_buf(max(1, mecalc)))
1076 DO i = istart, istart + mecalc - 1
1077 i_local = i - istart + 1
1078 ele_ind_buf(i_local) = int(nnp%ele_ind(i) - 1, c_int)
1081 ec = nnp_gpu_scale_g_dev_c(int(mecalc, c_int), int(n_input_max, c_int), &
1082 int(nnp%n_ele, c_int), int(scaling_mode, c_int), &
1083 REAL(nnp%scmin, c_double),
REAL(nnp%scmax, c_double), &
1085 IF (ec /= 0) cpabort(
"NNP GPU: descriptor scaling failed.")
1087 DEALLOCATE (ele_ind_buf)
1089 CALL timestop(handle)
1094 mark_used(n_input_max)
1096 cpabort(
"NNP GPU support is not compiled into this binary.")
1099 END SUBROUTINE nnp_gpu_build_descriptor
1114 TYPE(nnp_type),
INTENT(IN),
POINTER :: nnp
1118#if (defined(__OFFLOAD) || defined(__OFFLOAD_CUDA) || defined(__OFFLOAD_HIP)) && !defined(__NO_OFFLOAD_NNP)
1119 CHARACTER(len=*),
PARAMETER :: routinen =
'nnp_gpu_upload_network'
1120 INTEGER :: c, e, ec, i, idx_b, idx_w, j, l, max_n_nodes, n_com, n_ele, n_in, n_layer, n_out
1121 INTEGER(KIND=c_int),
ALLOCATABLE,
DIMENSION(:) :: act_fnct_buf, n_nodes_buf
1122 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:) :: b_packed_buf, w_packed_buf
1124 CALL timeset(routinen, handle)
1126 n_com = nnp%n_committee
1127 n_layer = nnp%n_layer
1136 IF (nnp%arc(e)%n_nodes(l) > max_n_nodes) max_n_nodes = nnp%arc(e)%n_nodes(l)
1141 ALLOCATE (n_nodes_buf(n_layer*n_ele))
1144 n_nodes_buf((l - 1) + n_layer*(e - 1) + 1) = int(nnp%arc(e)%n_nodes(l), c_int)
1149 ALLOCATE (act_fnct_buf(n_layer - 1))
1151 act_fnct_buf(l - 1) = int(nnp%actfnct(l - 1), c_int)
1159 ALLOCATE (w_packed_buf(max_n_nodes*max_n_nodes*n_com*(n_layer - 1)*n_ele))
1160 ALLOCATE (b_packed_buf(max_n_nodes*n_com*(n_layer - 1)*n_ele))
1161 w_packed_buf = 0.0_dp
1162 b_packed_buf = 0.0_dp
1165 n_in = nnp%arc(e)%n_nodes(l - 1)
1166 n_out = nnp%arc(e)%n_nodes(l)
1170 idx_w = (i - 1) + max_n_nodes*(j - 1) + &
1171 max_n_nodes*max_n_nodes*(c - 1) + &
1172 max_n_nodes*max_n_nodes*n_com*(l - 2) + &
1173 max_n_nodes*max_n_nodes*n_com*(n_layer - 1)*(e - 1) + 1
1174 w_packed_buf(idx_w) = nnp%arc(e)%layer(l)%weights(i, j, c)
1176 idx_b = (j - 1) + max_n_nodes*(c - 1) + &
1177 max_n_nodes*n_com*(l - 2) + &
1178 max_n_nodes*n_com*(n_layer - 1)*(e - 1) + 1
1179 b_packed_buf(idx_b) = nnp%arc(e)%layer(l)%bweights(j, c)
1185 ec = nnp_gpu_upload_nn_packed_c(int(n_com, c_int), int(n_layer, c_int), &
1186 int(max_n_nodes, c_int), int(n_ele, c_int), &
1187 n_nodes_buf, act_fnct_buf, nnp%atom_energies, &
1188 w_packed_buf, b_packed_buf)
1189 IF (ec /= 0) cpabort(
"NNP GPU: committee network upload failed.")
1191 DEALLOCATE (n_nodes_buf, act_fnct_buf, w_packed_buf, b_packed_buf)
1193 CALL timestop(handle)
1197 cpabort(
"NNP GPU support is not compiled into this binary.")
1219 SUBROUTINE nnp_gpu_predict(nnp, istart, mecalc, n_input_max)
1220 TYPE(nnp_type),
INTENT(INOUT),
POINTER :: nnp
1221 INTEGER,
INTENT(IN) :: istart, mecalc, n_input_max
1225#if (defined(__OFFLOAD) || defined(__OFFLOAD_CUDA) || defined(__OFFLOAD_HIP)) && !defined(__NO_OFFLOAD_NNP)
1226 CHARACTER(len=*),
PARAMETER :: routinen =
'nnp_gpu_predict'
1227 INTEGER :: atom_local, c, e, ec, i, l, max_n_nodes, n_com, n_ele, n_layer
1228 INTEGER(KIND=c_int),
ALLOCATABLE,
DIMENSION(:) :: ele_ind_buf
1229 REAL(kind=c_double),
ALLOCATABLE,
DIMENSION(:) :: h_atomic_energy
1231 CALL timeset(routinen, handle)
1233 n_com = nnp%n_committee
1234 n_layer = nnp%n_layer
1237 IF (mecalc <= 0)
THEN
1238 CALL timestop(handle)
1247 IF (nnp%arc(e)%n_nodes(l) > max_n_nodes) max_n_nodes = nnp%arc(e)%n_nodes(l)
1252 ALLOCATE (ele_ind_buf(mecalc))
1253 DO i = istart, istart + mecalc - 1
1254 atom_local = i - istart + 1
1255 ele_ind_buf(atom_local) = int(nnp%ele_ind(i) - 1, c_int)
1261 ALLOCATE (h_atomic_energy(n_com*mecalc))
1262 h_atomic_energy = 0.0_c_double
1264 ec = nnp_gpu_nn_atomwise_with_g_dev_c(int(mecalc, c_int), int(n_com, c_int), &
1265 int(n_layer, c_int), int(max_n_nodes, c_int), &
1266 int(n_input_max, c_int), &
1267 merge(1_c_int, 0_c_int, nnp%normnodes), &
1268 int(n_ele, c_int), ele_ind_buf, &
1269 h_atomic_energy, c_null_ptr)
1270 IF (ec /= 0) cpabort(
"NNP GPU: committee network evaluation failed.")
1277 DO atom_local = 1, mecalc
1278 i = istart + atom_local - 1
1280 nnp%atomic_energy(i, c) = h_atomic_energy((c - 1) + n_com*(atom_local - 1) + 1)
1284 DEALLOCATE (ele_ind_buf, h_atomic_energy)
1286 CALL timestop(handle)
1291 mark_used(n_input_max)
1293 cpabort(
"NNP GPU support is not compiled into this binary.")
1296 END SUBROUTINE nnp_gpu_predict
1318 TYPE(nnp_type),
INTENT(INOUT),
POINTER :: nnp
1319 INTEGER,
INTENT(IN) :: istart, mecalc, n_input_max
1320 LOGICAL,
INTENT(IN) :: calc_stress
1324#if (defined(__OFFLOAD) || defined(__OFFLOAD_CUDA) || defined(__OFFLOAD_HIP)) && !defined(__NO_OFFLOAD_NNP)
1325 CHARACTER(len=*),
PARAMETER :: routinen =
'nnp_gpu_energy_force'
1326 INTEGER :: accumulate_virial, e, ec, iva, ivb, ivc, max_n_ang1, max_n_ang2, max_n_anggrp, &
1327 max_n_kk, max_n_neigh_per_se, max_n_radgrp, n_atoms_e, s, scaling_mode
1329 REAL(kind=c_double),
ALLOCATABLE :: c_virial(:)
1331 CALL timeset(routinen, handle)
1337 IF (mecalc <= 0)
THEN
1338 CALL timestop(handle)
1345 accumulate_virial = merge(1, 0, calc_stress)
1349 CALL nnp_gpu_run_walk(nnp, istart, mecalc)
1350 CALL nnp_gpu_build_descriptor(nnp, istart, mecalc, n_input_max)
1351 CALL nnp_gpu_predict(nnp, istart, mecalc, n_input_max)
1357 IF (nnp%scale_sigma_acsf)
THEN
1359 ELSE IF (nnp%center_acsf .AND. nnp%scale_acsf)
THEN
1361 ELSE IF (nnp%center_acsf)
THEN
1363 ELSE IF (nnp%scale_acsf)
THEN
1371 CALL nnp_gpu_max_symfgrp(nnp, max_n_radgrp, max_n_anggrp)
1375 ec = nnp_gpu_force_scatter_begin_c(int(nnp%num_atoms, c_int), &
1376 int(nnp%n_committee, c_int), nnp%myforce)
1377 IF (ec /= 0) cpabort(
"NNP GPU: force-scatter begin failed.")
1379 associate(hstate => nnp%gpu_host_state)
1383 n_atoms_e = hstate%n_atoms_in_e(e)
1384 IF (n_atoms_e <= 0) cycle
1385 DO s = 1, nnp%rad(e)%n_symfgrp
1386 associate(symfgrp => nnp%rad(e)%symfgrp(s))
1387 max_n_neigh_per_se = maxval(hstate%n_rad_pa(1:n_atoms_e, s, e))
1388 IF (max_n_neigh_per_se <= 0) cycle
1389 ec = nnp_gpu_force_scatter_radial_c( &
1390 int(n_atoms_e, c_int), int(symfgrp%n_symf, c_int), &
1391 int(max_n_neigh_per_se, c_int), int(nnp%n_committee, c_int), &
1392 int(n_input_max, c_int), int(nnp%num_atoms, c_int), &
1393 int(e - 1, c_int), int(scaling_mode, c_int), &
1394 REAL(nnp%scmin, c_double),
REAL(nnp%scmax, c_double), &
1395 int(s - 1, c_int), int(max_n_radgrp, c_int), &
1396 int(hstate%n_atoms_in_e_max, c_int), &
1397 int(hstate%max_n_neigh_rad, c_int), int(istart, c_int), &
1398 int((s - 1) + max_n_radgrp*(e - 1), c_int), &
1399 int(accumulate_virial, c_int))
1400 IF (ec /= 0) cpabort(
"NNP GPU: radial force-scatter kernel failed.")
1412 n_atoms_e = hstate%n_atoms_in_e(e)
1413 IF (n_atoms_e <= 0) cycle
1414 DO s = 1, nnp%ang(e)%n_symfgrp
1415 associate(symfgrp => nnp%ang(e)%symfgrp(s))
1416 homo = (symfgrp%ele(1) == symfgrp%ele(2))
1417 max_n_ang1 = maxval(hstate%n_ang1_pa(1:n_atoms_e, s, e))
1418 IF (max_n_ang1 <= 0) cycle
1421 max_n_kk = max(1, max_n_ang1)
1423 max_n_ang2 = maxval(hstate%n_ang2_pa(1:n_atoms_e, s, e))
1429 IF (max_n_ang2 <= 0) cycle
1430 max_n_kk = max(1, max_n_ang2)
1432 ec = nnp_gpu_force_scatter_angular_c( &
1433 int(n_atoms_e, c_int), int(symfgrp%n_symf, c_int), &
1434 int(max(1, max_n_ang1), c_int), int(max_n_kk, c_int), &
1435 int(nnp%n_committee, c_int), int(n_input_max, c_int), &
1436 int(nnp%num_atoms, c_int), int(e - 1, c_int), &
1437 int(nnp%n_rad(e), c_int), int(scaling_mode, c_int), &
1438 int(merge(1, 0, homo), c_int), real(nnp%scmin, c_double), &
1439 REAL(nnp%scmax, c_double), int(s - 1, c_int), &
1440 int(max_n_anggrp, c_int), int(hstate%n_atoms_in_e_max, c_int), &
1441 int(hstate%max_n_neigh_ang1, c_int), &
1442 int(hstate%max_n_neigh_ang2, c_int), int(istart, c_int), &
1443 int((s - 1) + max_n_anggrp*(e - 1), c_int), &
1444 int(accumulate_virial, c_int))
1445 IF (ec /= 0) cpabort(
"NNP GPU: angular force-scatter kernel failed.")
1453 ec = nnp_gpu_force_scatter_end_c(int(nnp%num_atoms, c_int), &
1454 int(nnp%n_committee, c_int), nnp%myforce)
1455 IF (ec /= 0) cpabort(
"NNP GPU: force-scatter end failed.")
1463 IF (accumulate_virial /= 0)
THEN
1464 ALLOCATE (c_virial(9*nnp%n_committee))
1465 ec = nnp_gpu_force_scatter_virial_d2h_c(int(nnp%n_committee, c_int), c_virial)
1466 IF (ec /= 0) cpabort(
"NNP GPU: force-scatter virial read-back failed.")
1467 DO ivc = 1, nnp%n_committee
1470 nnp%committee_stress(ivb, iva, ivc) = &
1471 nnp%committee_stress(ivb, iva, ivc) + &
1472 c_virial(9*(ivc - 1) + 3*(iva - 1) + (ivb - 1) + 1)
1476 DEALLOCATE (c_virial)
1483 nnp%output_expol = (nnp_gpu_extrapolation_flag_c() /= 0)
1485 CALL timestop(handle)
1490 mark_used(n_input_max)
1491 mark_used(calc_stress)
1493 cpabort(
"NNP GPU support is not compiled into this binary.")
Defines the basic variable types.
integer, parameter, public dp
Functionality for atom centered symmetry functions for neural network potentials.
subroutine, public nnp_build_radial_splines(nnp)
Build sf-first (n_symf, n_grid) Hermite cubic spline tables for radial SFs. Uses a custom sf-first la...
Data types for neural network potentials.
GPU offload driver for the NNP force evaluation. Hosts the ISO_C_BINDING interfaces to the CUDA launc...
subroutine, public nnp_gpu_init_device(gpu_precision, accepted)
Claim the offload device for this NNP environment and push the requested compute precision to the dev...
logical function, public nnp_gpu_model_capacity_ok(nnp, reason)
Test whether the model fits the compiled-in device-table capacities: NNP_MAX_SE (group,...
subroutine, public nnp_gpu_upload_descriptor_statics(nnp)
Upload the model-static descriptor tables to the device once at NNP initialization: the per-element s...
subroutine, public nnp_gpu_energy_force(nnp, istart, mecalc, n_input_max, calc_stress)
Run the whole per-step NNP force evaluation on the device: the cell-list walk, the descriptor build,...
logical function, public nnp_gpu_available()
Report whether the NNP GPU backend can run: the build must enable it and at least one offload device ...
subroutine, public nnp_gpu_upload_network(nnp)
Upload the committee network to the device once at NNP initialization: the per-element layer topology...
Fortran API for the offload package, which is written in C.
subroutine, public offload_activate_chosen_device()
Activates the device selected via offload_set_chosen_device().
integer function, public offload_get_device_count()
Returns the number of available devices.
subroutine, public offload_init()
Initialize runtime.
Main data type collecting all relevant data for neural network potentials.