29#include "./base/base_uses.f90"
52 CHARACTER(len=*),
PARAMETER :: routinen =
'nnp_neighbor_interface_prepare'
57 CALL timeset(routinen, handle)
59 rebuild = .NOT. nnp%neighbor_interface_state%initialized
60 IF (.NOT. rebuild)
CALL nnp_neighbor_interface_needs_rebuild(nnp, rebuild)
64 CALL nnp_neighbor_interface_build_pair_maps(nnp)
82 INTEGER,
INTENT(IN) :: ind
88 nnp%neighbor_interface_state%workspace(ind, tid)%neighbor%n_rad(:) = 0
89 nnp%neighbor_interface_state%workspace(ind, tid)%neighbor%n_ang1(:) = 0
90 nnp%neighbor_interface_state%workspace(ind, tid)%neighbor%n_ang2(:) = 0
101 SUBROUTINE nnp_neighbor_interface_needs_rebuild(nnp, rebuild)
104 LOGICAL,
INTENT(OUT) :: rebuild
109 IF (nnp%neighbor_interface_state%n_ele /= nnp%n_ele)
THEN
113 IF (.NOT.
ALLOCATED(nnp%neighbor_interface_state%n_rad))
THEN
119 IF (nnp%neighbor_interface_state%n_rad(i) /= nnp%n_rad(i) .OR. &
120 nnp%neighbor_interface_state%n_ang(i) /= nnp%n_ang(i) .OR. &
121 nnp%neighbor_interface_state%n_radgrp(i) /= nnp%rad(i)%n_symfgrp .OR. &
122 nnp%neighbor_interface_state%n_anggrp(i) /= nnp%ang(i)%n_symfgrp)
THEN
128 END SUBROUTINE nnp_neighbor_interface_needs_rebuild
134 SUBROUTINE nnp_neighbor_interface_build_pair_maps(nnp)
136 TYPE(
nnp_type),
INTENT(INOUT) :: nnp
138 INTEGER :: i, nthreads, t
140 associate(state => nnp%neighbor_interface_state)
141 state%n_ele = nnp%n_ele
142 ALLOCATE (state%n_rad(nnp%n_ele))
143 ALLOCATE (state%n_ang(nnp%n_ele))
144 ALLOCATE (state%n_radgrp(nnp%n_ele))
145 ALLOCATE (state%n_anggrp(nnp%n_ele))
146 ALLOCATE (state%pair_map(nnp%n_ele, nnp%n_ele))
150 ALLOCATE (state%workspace(nnp%n_ele, nthreads))
153 state%n_rad(i) = nnp%n_rad(i)
154 state%n_ang(i) = nnp%n_ang(i)
155 state%n_radgrp(i) = nnp%rad(i)%n_symfgrp
156 state%n_anggrp(i) = nnp%ang(i)%n_symfgrp
160 CALL nnp_neighbor_interface_build_pair_map_for_element(nnp, i)
162 CALL nnp_neighbor_interface_init_workspace_metadata(nnp, i, t)
166 state%initialized = .true.
169 END SUBROUTINE nnp_neighbor_interface_build_pair_maps
176 SUBROUTINE nnp_neighbor_interface_build_pair_map_for_element(nnp, ind)
178 TYPE(nnp_type),
INTENT(INOUT) :: nnp
179 INTEGER,
INTENT(IN) :: ind
181 INTEGER ::
idx, neighbor_ind, s
183 DO neighbor_ind = 1, nnp%n_ele
184 associate(pair_map => nnp%neighbor_interface_state%pair_map(ind, neighbor_ind))
188 pair_map%max_relevant_cutoff = 0.0_dp
190 DO s = 1, nnp%rad(ind)%n_symfgrp
191 IF (nnp%rad(ind)%symfgrp(s)%ele_ind(1) == neighbor_ind) pair_map%n_rad = pair_map%n_rad + 1
193 DO s = 1, nnp%ang(ind)%n_symfgrp
194 IF (nnp%ang(ind)%symfgrp(s)%ele_ind(1) == neighbor_ind) pair_map%n_ang1 = pair_map%n_ang1 + 1
195 IF (nnp%ang(ind)%symfgrp(s)%ele_ind(2) == neighbor_ind) pair_map%n_ang2 = pair_map%n_ang2 + 1
198 ALLOCATE (pair_map%rad_groups(max(1, pair_map%n_rad)))
199 ALLOCATE (pair_map%ang1_groups(max(1, pair_map%n_ang1)))
200 ALLOCATE (pair_map%ang2_groups(max(1, pair_map%n_ang2)))
203 DO s = 1, nnp%rad(ind)%n_symfgrp
204 IF (nnp%rad(ind)%symfgrp(s)%ele_ind(1) == neighbor_ind)
THEN
206 pair_map%rad_groups(
idx) = s
207 pair_map%max_relevant_cutoff = max(pair_map%max_relevant_cutoff, nnp%rad(ind)%symfgrp(s)%cutoff)
212 DO s = 1, nnp%ang(ind)%n_symfgrp
213 IF (nnp%ang(ind)%symfgrp(s)%ele_ind(1) == neighbor_ind)
THEN
215 pair_map%ang1_groups(
idx) = s
216 pair_map%max_relevant_cutoff = max(pair_map%max_relevant_cutoff, nnp%ang(ind)%symfgrp(s)%cutoff)
221 DO s = 1, nnp%ang(ind)%n_symfgrp
222 IF (nnp%ang(ind)%symfgrp(s)%ele_ind(2) == neighbor_ind)
THEN
224 pair_map%ang2_groups(
idx) = s
225 pair_map%max_relevant_cutoff = max(pair_map%max_relevant_cutoff, nnp%ang(ind)%symfgrp(s)%cutoff)
231 END SUBROUTINE nnp_neighbor_interface_build_pair_map_for_element
239 SUBROUTINE nnp_neighbor_interface_init_workspace_metadata(nnp, ind, tid)
241 TYPE(nnp_type),
INTENT(INOUT) :: nnp
242 INTEGER,
INTENT(IN) :: ind, tid
246 associate(workspace => nnp%neighbor_interface_state%workspace(ind, tid))
247 workspace%max_rad_symf = 0
248 workspace%max_ang_symf = 0
249 workspace%n_input_nodes = nnp%n_rad(ind) + nnp%n_ang(ind)
251 DO s = 1, nnp%rad(ind)%n_symfgrp
252 workspace%max_rad_symf = max(workspace%max_rad_symf, nnp%rad(ind)%symfgrp(s)%n_symf)
254 DO s = 1, nnp%ang(ind)%n_symfgrp
255 workspace%max_ang_symf = max(workspace%max_ang_symf, nnp%ang(ind)%symfgrp(s)%n_symf)
259 IF (
ALLOCATED(workspace%radial_sym))
DEALLOCATE (workspace%radial_sym)
260 IF (
ALLOCATED(workspace%radial_force))
DEALLOCATE (workspace%radial_force)
261 IF (
ALLOCATED(workspace%angular_sym))
DEALLOCATE (workspace%angular_sym)
262 IF (
ALLOCATED(workspace%angular_force))
DEALLOCATE (workspace%angular_force)
263 ALLOCATE (workspace%radial_sym(max(1, workspace%max_rad_symf)))
264 ALLOCATE (workspace%radial_force(3, max(1, workspace%max_rad_symf)))
265 ALLOCATE (workspace%angular_sym(max(1, workspace%max_ang_symf)))
266 ALLOCATE (workspace%angular_force(3, 3, max(1, workspace%max_ang_symf)))
270 IF (
ALLOCATED(workspace%fc_cache1))
DEALLOCATE (workspace%fc_cache1)
271 IF (
ALLOCATED(workspace%dfc_cache1))
DEALLOCATE (workspace%dfc_cache1)
272 IF (
ALLOCATED(workspace%fc_cache2))
DEALLOCATE (workspace%fc_cache2)
273 IF (
ALLOCATED(workspace%dfc_cache2))
DEALLOCATE (workspace%dfc_cache2)
274 workspace%cache_cap = 8
275 ALLOCATE (workspace%fc_cache1(workspace%cache_cap))
276 ALLOCATE (workspace%dfc_cache1(workspace%cache_cap))
277 ALLOCATE (workspace%fc_cache2(workspace%cache_cap))
278 ALLOCATE (workspace%dfc_cache2(workspace%cache_cap))
281 IF (
ALLOCATED(workspace%self_dGdr))
DEALLOCATE (workspace%self_dGdr)
282 ALLOCATE (workspace%self_dGdr(3, max(1, workspace%n_input_nodes)))
286 CALL nnp_release_neighbor_local(workspace)
287 ALLOCATE (workspace%neighbor%n_rad(max(1, nnp%rad(ind)%n_symfgrp)))
288 ALLOCATE (workspace%neighbor%n_ang1(max(1, nnp%ang(ind)%n_symfgrp)))
289 ALLOCATE (workspace%neighbor%n_ang2(max(1, nnp%ang(ind)%n_symfgrp)))
290 ALLOCATE (workspace%neighbor%rad(max(1, nnp%rad(ind)%n_symfgrp)))
291 ALLOCATE (workspace%neighbor%ang1(max(1, nnp%ang(ind)%n_symfgrp)))
292 ALLOCATE (workspace%neighbor%ang2(max(1, nnp%ang(ind)%n_symfgrp)))
293 workspace%neighbor%n_rad(:) = 0
294 workspace%neighbor%n_ang1(:) = 0
295 workspace%neighbor%n_ang2(:) = 0
296 workspace%neighbor%pbc_copies = 0
301 CALL nnp_release_dgdr_grp_array(workspace%dGdr_rad)
302 CALL nnp_release_dgdr_grp_array(workspace%dGdr_ang_jj)
303 CALL nnp_release_dgdr_grp_array(workspace%dGdr_ang_kk)
304 ALLOCATE (workspace%dGdr_rad(max(1, nnp%rad(ind)%n_symfgrp)))
305 ALLOCATE (workspace%dGdr_ang_jj(max(1, nnp%ang(ind)%n_symfgrp)))
306 ALLOCATE (workspace%dGdr_ang_kk(max(1, nnp%ang(ind)%n_symfgrp)))
307 DO s = 1, nnp%rad(ind)%n_symfgrp
308 workspace%dGdr_rad(s)%n_symf = nnp%rad(ind)%symfgrp(s)%n_symf
309 workspace%dGdr_rad(s)%cap = 0
311 DO s = 1, nnp%ang(ind)%n_symfgrp
312 workspace%dGdr_ang_jj(s)%n_symf = nnp%ang(ind)%symfgrp(s)%n_symf
313 workspace%dGdr_ang_jj(s)%cap = 0
314 workspace%dGdr_ang_kk(s)%n_symf = nnp%ang(ind)%symfgrp(s)%n_symf
315 workspace%dGdr_ang_kk(s)%cap = 0
319 END SUBROUTINE nnp_neighbor_interface_init_workspace_metadata
326 SUBROUTINE nnp_release_neighbor_local(workspace)
328 TYPE(nnp_neighbor_workspace_type),
INTENT(INOUT) :: workspace
332 IF (
ALLOCATED(workspace%neighbor%rad))
THEN
333 DO s = 1,
SIZE(workspace%neighbor%rad)
334 IF (
ALLOCATED(workspace%neighbor%rad(s)%ind))
DEALLOCATE (workspace%neighbor%rad(s)%ind)
335 IF (
ALLOCATED(workspace%neighbor%rad(s)%dist))
DEALLOCATE (workspace%neighbor%rad(s)%dist)
337 DEALLOCATE (workspace%neighbor%rad)
339 IF (
ALLOCATED(workspace%neighbor%ang1))
THEN
340 DO s = 1,
SIZE(workspace%neighbor%ang1)
341 IF (
ALLOCATED(workspace%neighbor%ang1(s)%ind))
DEALLOCATE (workspace%neighbor%ang1(s)%ind)
342 IF (
ALLOCATED(workspace%neighbor%ang1(s)%dist))
DEALLOCATE (workspace%neighbor%ang1(s)%dist)
344 DEALLOCATE (workspace%neighbor%ang1)
346 IF (
ALLOCATED(workspace%neighbor%ang2))
THEN
347 DO s = 1,
SIZE(workspace%neighbor%ang2)
348 IF (
ALLOCATED(workspace%neighbor%ang2(s)%ind))
DEALLOCATE (workspace%neighbor%ang2(s)%ind)
349 IF (
ALLOCATED(workspace%neighbor%ang2(s)%dist))
DEALLOCATE (workspace%neighbor%ang2(s)%dist)
351 DEALLOCATE (workspace%neighbor%ang2)
353 IF (
ALLOCATED(workspace%neighbor%n_rad))
DEALLOCATE (workspace%neighbor%n_rad)
354 IF (
ALLOCATED(workspace%neighbor%n_ang1))
DEALLOCATE (workspace%neighbor%n_ang1)
355 IF (
ALLOCATED(workspace%neighbor%n_ang2))
DEALLOCATE (workspace%neighbor%n_ang2)
356 workspace%neighbor%pbc_copies = -1
358 END SUBROUTINE nnp_release_neighbor_local
364 SUBROUTINE nnp_release_dgdr_grp_array(grps)
366 TYPE(nnp_dgdr_grp_type),
ALLOCATABLE, &
367 INTENT(INOUT) :: grps(:)
371 IF (.NOT.
ALLOCATED(grps))
RETURN
373 IF (
ALLOCATED(grps(s)%data))
DEALLOCATE (grps(s)%data)
379 END SUBROUTINE nnp_release_dgdr_grp_array
392 TYPE(nnp_dgdr_grp_type),
INTENT(INOUT) :: grp
393 INTEGER,
INTENT(IN) :: n_needed
397 IF (
ALLOCATED(grp%data) .AND. grp%cap >= n_needed)
RETURN
398 IF (
ALLOCATED(grp%data))
DEALLOCATE (grp%data)
399 new_cap = max(max(1, n_needed), int(grp%cap*1.5_dp) + 8)
400 ALLOCATE (grp%data(3, max(1, grp%n_symf), new_cap))
416 TYPE(nnp_neigh_grp_type),
INTENT(INOUT) :: grp
417 INTEGER,
INTENT(IN) :: n_needed
419 INTEGER :: n_old, new_cap
420 INTEGER,
ALLOCATABLE :: new_ind(:)
421 REAL(kind=dp),
ALLOCATABLE :: new_dist(:, :)
423 IF (
ALLOCATED(grp%dist) .AND. grp%cap >= n_needed)
RETURN
425 new_cap = max(max(8, n_needed), int(grp%cap*1.5_dp) + 8)
427 IF (
ALLOCATED(grp%dist))
THEN
429 ALLOCATE (new_dist(4, new_cap))
430 ALLOCATE (new_ind(new_cap))
432 new_dist(:, 1:n_old) = grp%dist(:, 1:n_old)
433 new_ind(1:n_old) = grp%ind(1:n_old)
435 CALL move_alloc(new_dist, grp%dist)
436 CALL move_alloc(new_ind, grp%ind)
438 ALLOCATE (grp%dist(4, new_cap))
439 ALLOCATE (grp%ind(new_cap))
456 TYPE(nnp_neighbor_workspace_type),
INTENT(INOUT) :: workspace
457 INTEGER,
INTENT(IN) :: n_needed
461 IF (workspace%cache_cap >= n_needed)
RETURN
463 new_cap = max(max(8, n_needed), int(workspace%cache_cap*1.5_dp) + 8)
465 IF (
ALLOCATED(workspace%fc_cache1))
DEALLOCATE (workspace%fc_cache1)
466 IF (
ALLOCATED(workspace%dfc_cache1))
DEALLOCATE (workspace%dfc_cache1)
467 IF (
ALLOCATED(workspace%fc_cache2))
DEALLOCATE (workspace%fc_cache2)
468 IF (
ALLOCATED(workspace%dfc_cache2))
DEALLOCATE (workspace%dfc_cache2)
469 ALLOCATE (workspace%fc_cache1(new_cap))
470 ALLOCATE (workspace%dfc_cache1(new_cap))
471 ALLOCATE (workspace%fc_cache2(new_cap))
472 ALLOCATE (workspace%dfc_cache2(new_cap))
473 workspace%cache_cap = new_cap
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
Defines the basic variable types.
integer, parameter, public dp
Data types for neural network potentials.
subroutine, public nnp_neighbor_interface_state_release(state)
Free the allocatable parts of a neighbour-interface state. Co-located with the type definition to avo...
Per-nnp persistent neighbour-interface state for the NNP hot path. Separates neighbour bookkeeping fr...
subroutine, public nnp_grp_grow_dgdr(grp, n_needed)
Ensure a per-group dG/dr buffer holds n_needed neighbours, growing by 1.5x (with an additive floor) s...
subroutine, public nnp_neigh_grp_grow(grp, n_needed)
Ensure a per-group (ind, dist) neighbour buffer holds n_needed entries. Called from inside the linked...
subroutine, public nnp_workspace_grow_caches(workspace, n_needed)
Ensure the four per-element angular cutoff caches hold at least n_needed entries. These 1D scratch ar...
subroutine, public nnp_neighbor_interface_reset_neighbor(nnp, ind)
Reset per-group neighbour counters for one central element before refilling the reusable buffers....
subroutine, public nnp_neighbor_interface_prepare(nnp)
Ensure pair-routing metadata and reusable workspaces are ready for the current NNP model.
Per-(element, SF-group) dG_k/dr buffer, sized to the group's n_symf (no max_*_symf padding) and the o...
Per-SF-group dense neighbour container. cap is the allocated slab size; the live count is nnp_neighbo...
Reusable per-element scratch / persistent caches for the ACSF descriptor and force assembly....
Main data type collecting all relevant data for neural network potentials.