27#include "./base/base_uses.f90"
50 CHARACTER(len=*),
PARAMETER :: routinen =
'nnp_neighbor_interface_prepare'
55 CALL timeset(routinen, handle)
57 rebuild = .NOT. nnp%neighbor_interface_state%initialized
58 IF (.NOT. rebuild)
CALL nnp_neighbor_interface_needs_rebuild(nnp, rebuild)
62 CALL nnp_neighbor_interface_build_pair_maps(nnp)
80 INTEGER,
INTENT(IN) :: ind
82 nnp%neighbor_interface_state%workspace(ind)%neighbor%n_rad(:) = 0
83 nnp%neighbor_interface_state%workspace(ind)%neighbor%n_ang1(:) = 0
84 nnp%neighbor_interface_state%workspace(ind)%neighbor%n_ang2(:) = 0
95 SUBROUTINE nnp_neighbor_interface_needs_rebuild(nnp, rebuild)
98 LOGICAL,
INTENT(OUT) :: rebuild
103 IF (nnp%neighbor_interface_state%n_ele /= nnp%n_ele)
THEN
107 IF (.NOT.
ALLOCATED(nnp%neighbor_interface_state%n_rad))
THEN
113 IF (nnp%neighbor_interface_state%n_rad(i) /= nnp%n_rad(i) .OR. &
114 nnp%neighbor_interface_state%n_ang(i) /= nnp%n_ang(i) .OR. &
115 nnp%neighbor_interface_state%n_radgrp(i) /= nnp%rad(i)%n_symfgrp .OR. &
116 nnp%neighbor_interface_state%n_anggrp(i) /= nnp%ang(i)%n_symfgrp)
THEN
122 END SUBROUTINE nnp_neighbor_interface_needs_rebuild
128 SUBROUTINE nnp_neighbor_interface_build_pair_maps(nnp)
130 TYPE(
nnp_type),
INTENT(INOUT) :: nnp
134 associate(state => nnp%neighbor_interface_state)
135 state%n_ele = nnp%n_ele
136 ALLOCATE (state%n_rad(nnp%n_ele))
137 ALLOCATE (state%n_ang(nnp%n_ele))
138 ALLOCATE (state%n_radgrp(nnp%n_ele))
139 ALLOCATE (state%n_anggrp(nnp%n_ele))
140 ALLOCATE (state%pair_map(nnp%n_ele, nnp%n_ele))
141 ALLOCATE (state%workspace(nnp%n_ele))
144 state%n_rad(i) = nnp%n_rad(i)
145 state%n_ang(i) = nnp%n_ang(i)
146 state%n_radgrp(i) = nnp%rad(i)%n_symfgrp
147 state%n_anggrp(i) = nnp%ang(i)%n_symfgrp
151 CALL nnp_neighbor_interface_build_pair_map_for_element(nnp, i)
152 CALL nnp_neighbor_interface_init_workspace_metadata(nnp, i)
155 state%initialized = .true.
158 END SUBROUTINE nnp_neighbor_interface_build_pair_maps
165 SUBROUTINE nnp_neighbor_interface_build_pair_map_for_element(nnp, ind)
167 TYPE(nnp_type),
INTENT(INOUT) :: nnp
168 INTEGER,
INTENT(IN) :: ind
170 INTEGER ::
idx, neighbor_ind, s
172 DO neighbor_ind = 1, nnp%n_ele
173 associate(pair_map => nnp%neighbor_interface_state%pair_map(ind, neighbor_ind))
177 pair_map%max_relevant_cutoff = 0.0_dp
179 DO s = 1, nnp%rad(ind)%n_symfgrp
180 IF (nnp%rad(ind)%symfgrp(s)%ele_ind(1) == neighbor_ind) pair_map%n_rad = pair_map%n_rad + 1
182 DO s = 1, nnp%ang(ind)%n_symfgrp
183 IF (nnp%ang(ind)%symfgrp(s)%ele_ind(1) == neighbor_ind) pair_map%n_ang1 = pair_map%n_ang1 + 1
184 IF (nnp%ang(ind)%symfgrp(s)%ele_ind(2) == neighbor_ind) pair_map%n_ang2 = pair_map%n_ang2 + 1
187 ALLOCATE (pair_map%rad_groups(max(1, pair_map%n_rad)))
188 ALLOCATE (pair_map%ang1_groups(max(1, pair_map%n_ang1)))
189 ALLOCATE (pair_map%ang2_groups(max(1, pair_map%n_ang2)))
192 DO s = 1, nnp%rad(ind)%n_symfgrp
193 IF (nnp%rad(ind)%symfgrp(s)%ele_ind(1) == neighbor_ind)
THEN
195 pair_map%rad_groups(
idx) = s
196 pair_map%max_relevant_cutoff = max(pair_map%max_relevant_cutoff, nnp%rad(ind)%symfgrp(s)%cutoff)
201 DO s = 1, nnp%ang(ind)%n_symfgrp
202 IF (nnp%ang(ind)%symfgrp(s)%ele_ind(1) == neighbor_ind)
THEN
204 pair_map%ang1_groups(
idx) = s
205 pair_map%max_relevant_cutoff = max(pair_map%max_relevant_cutoff, nnp%ang(ind)%symfgrp(s)%cutoff)
210 DO s = 1, nnp%ang(ind)%n_symfgrp
211 IF (nnp%ang(ind)%symfgrp(s)%ele_ind(2) == neighbor_ind)
THEN
213 pair_map%ang2_groups(
idx) = s
214 pair_map%max_relevant_cutoff = max(pair_map%max_relevant_cutoff, nnp%ang(ind)%symfgrp(s)%cutoff)
220 END SUBROUTINE nnp_neighbor_interface_build_pair_map_for_element
227 SUBROUTINE nnp_neighbor_interface_init_workspace_metadata(nnp, ind)
229 TYPE(nnp_type),
INTENT(INOUT) :: nnp
230 INTEGER,
INTENT(IN) :: ind
234 associate(workspace => nnp%neighbor_interface_state%workspace(ind))
235 workspace%max_rad_symf = 0
236 workspace%max_ang_symf = 0
237 workspace%n_input_nodes = nnp%n_rad(ind) + nnp%n_ang(ind)
239 DO s = 1, nnp%rad(ind)%n_symfgrp
240 workspace%max_rad_symf = max(workspace%max_rad_symf, nnp%rad(ind)%symfgrp(s)%n_symf)
242 DO s = 1, nnp%ang(ind)%n_symfgrp
243 workspace%max_ang_symf = max(workspace%max_ang_symf, nnp%ang(ind)%symfgrp(s)%n_symf)
247 IF (
ALLOCATED(workspace%radial_sym))
DEALLOCATE (workspace%radial_sym)
248 IF (
ALLOCATED(workspace%radial_force))
DEALLOCATE (workspace%radial_force)
249 IF (
ALLOCATED(workspace%angular_sym))
DEALLOCATE (workspace%angular_sym)
250 IF (
ALLOCATED(workspace%angular_force))
DEALLOCATE (workspace%angular_force)
251 ALLOCATE (workspace%radial_sym(max(1, workspace%max_rad_symf)))
252 ALLOCATE (workspace%radial_force(3, max(1, workspace%max_rad_symf)))
253 ALLOCATE (workspace%angular_sym(max(1, workspace%max_ang_symf)))
254 ALLOCATE (workspace%angular_force(3, 3, max(1, workspace%max_ang_symf)))
258 IF (
ALLOCATED(workspace%fc_cache1))
DEALLOCATE (workspace%fc_cache1)
259 IF (
ALLOCATED(workspace%dfc_cache1))
DEALLOCATE (workspace%dfc_cache1)
260 IF (
ALLOCATED(workspace%fc_cache2))
DEALLOCATE (workspace%fc_cache2)
261 IF (
ALLOCATED(workspace%dfc_cache2))
DEALLOCATE (workspace%dfc_cache2)
262 workspace%cache_cap = 8
263 ALLOCATE (workspace%fc_cache1(workspace%cache_cap))
264 ALLOCATE (workspace%dfc_cache1(workspace%cache_cap))
265 ALLOCATE (workspace%fc_cache2(workspace%cache_cap))
266 ALLOCATE (workspace%dfc_cache2(workspace%cache_cap))
269 IF (
ALLOCATED(workspace%self_dGdr))
DEALLOCATE (workspace%self_dGdr)
270 ALLOCATE (workspace%self_dGdr(3, max(1, workspace%n_input_nodes)))
274 CALL nnp_release_neighbor_local(workspace)
275 ALLOCATE (workspace%neighbor%n_rad(max(1, nnp%rad(ind)%n_symfgrp)))
276 ALLOCATE (workspace%neighbor%n_ang1(max(1, nnp%ang(ind)%n_symfgrp)))
277 ALLOCATE (workspace%neighbor%n_ang2(max(1, nnp%ang(ind)%n_symfgrp)))
278 ALLOCATE (workspace%neighbor%rad(max(1, nnp%rad(ind)%n_symfgrp)))
279 ALLOCATE (workspace%neighbor%ang1(max(1, nnp%ang(ind)%n_symfgrp)))
280 ALLOCATE (workspace%neighbor%ang2(max(1, nnp%ang(ind)%n_symfgrp)))
281 workspace%neighbor%n_rad(:) = 0
282 workspace%neighbor%n_ang1(:) = 0
283 workspace%neighbor%n_ang2(:) = 0
284 workspace%neighbor%pbc_copies = 0
289 CALL nnp_release_dgdr_grp_array(workspace%dGdr_rad)
290 CALL nnp_release_dgdr_grp_array(workspace%dGdr_ang_jj)
291 CALL nnp_release_dgdr_grp_array(workspace%dGdr_ang_kk)
292 ALLOCATE (workspace%dGdr_rad(max(1, nnp%rad(ind)%n_symfgrp)))
293 ALLOCATE (workspace%dGdr_ang_jj(max(1, nnp%ang(ind)%n_symfgrp)))
294 ALLOCATE (workspace%dGdr_ang_kk(max(1, nnp%ang(ind)%n_symfgrp)))
295 DO s = 1, nnp%rad(ind)%n_symfgrp
296 workspace%dGdr_rad(s)%n_symf = nnp%rad(ind)%symfgrp(s)%n_symf
297 workspace%dGdr_rad(s)%cap = 0
299 DO s = 1, nnp%ang(ind)%n_symfgrp
300 workspace%dGdr_ang_jj(s)%n_symf = nnp%ang(ind)%symfgrp(s)%n_symf
301 workspace%dGdr_ang_jj(s)%cap = 0
302 workspace%dGdr_ang_kk(s)%n_symf = nnp%ang(ind)%symfgrp(s)%n_symf
303 workspace%dGdr_ang_kk(s)%cap = 0
307 END SUBROUTINE nnp_neighbor_interface_init_workspace_metadata
314 SUBROUTINE nnp_release_neighbor_local(workspace)
316 TYPE(nnp_neighbor_workspace_type),
INTENT(INOUT) :: workspace
320 IF (
ALLOCATED(workspace%neighbor%rad))
THEN
321 DO s = 1,
SIZE(workspace%neighbor%rad)
322 IF (
ALLOCATED(workspace%neighbor%rad(s)%ind))
DEALLOCATE (workspace%neighbor%rad(s)%ind)
323 IF (
ALLOCATED(workspace%neighbor%rad(s)%dist))
DEALLOCATE (workspace%neighbor%rad(s)%dist)
325 DEALLOCATE (workspace%neighbor%rad)
327 IF (
ALLOCATED(workspace%neighbor%ang1))
THEN
328 DO s = 1,
SIZE(workspace%neighbor%ang1)
329 IF (
ALLOCATED(workspace%neighbor%ang1(s)%ind))
DEALLOCATE (workspace%neighbor%ang1(s)%ind)
330 IF (
ALLOCATED(workspace%neighbor%ang1(s)%dist))
DEALLOCATE (workspace%neighbor%ang1(s)%dist)
332 DEALLOCATE (workspace%neighbor%ang1)
334 IF (
ALLOCATED(workspace%neighbor%ang2))
THEN
335 DO s = 1,
SIZE(workspace%neighbor%ang2)
336 IF (
ALLOCATED(workspace%neighbor%ang2(s)%ind))
DEALLOCATE (workspace%neighbor%ang2(s)%ind)
337 IF (
ALLOCATED(workspace%neighbor%ang2(s)%dist))
DEALLOCATE (workspace%neighbor%ang2(s)%dist)
339 DEALLOCATE (workspace%neighbor%ang2)
341 IF (
ALLOCATED(workspace%neighbor%n_rad))
DEALLOCATE (workspace%neighbor%n_rad)
342 IF (
ALLOCATED(workspace%neighbor%n_ang1))
DEALLOCATE (workspace%neighbor%n_ang1)
343 IF (
ALLOCATED(workspace%neighbor%n_ang2))
DEALLOCATE (workspace%neighbor%n_ang2)
344 workspace%neighbor%pbc_copies = -1
346 END SUBROUTINE nnp_release_neighbor_local
352 SUBROUTINE nnp_release_dgdr_grp_array(grps)
354 TYPE(nnp_dgdr_grp_type),
ALLOCATABLE, &
355 INTENT(INOUT) :: grps(:)
359 IF (.NOT.
ALLOCATED(grps))
RETURN
361 IF (
ALLOCATED(grps(s)%data))
DEALLOCATE (grps(s)%data)
367 END SUBROUTINE nnp_release_dgdr_grp_array
380 TYPE(nnp_dgdr_grp_type),
INTENT(INOUT) :: grp
381 INTEGER,
INTENT(IN) :: n_needed
385 IF (
ALLOCATED(grp%data) .AND. grp%cap >= n_needed)
RETURN
386 IF (
ALLOCATED(grp%data))
DEALLOCATE (grp%data)
387 new_cap = max(max(1, n_needed), int(grp%cap*1.5_dp) + 8)
388 ALLOCATE (grp%data(3, max(1, grp%n_symf), new_cap))
404 TYPE(nnp_neigh_grp_type),
INTENT(INOUT) :: grp
405 INTEGER,
INTENT(IN) :: n_needed
407 INTEGER :: n_old, new_cap
408 INTEGER,
ALLOCATABLE :: new_ind(:)
409 REAL(kind=dp),
ALLOCATABLE :: new_dist(:, :)
411 IF (
ALLOCATED(grp%dist) .AND. grp%cap >= n_needed)
RETURN
413 new_cap = max(max(8, n_needed), int(grp%cap*1.5_dp) + 8)
415 IF (
ALLOCATED(grp%dist))
THEN
417 ALLOCATE (new_dist(4, new_cap))
418 ALLOCATE (new_ind(new_cap))
420 new_dist(:, 1:n_old) = grp%dist(:, 1:n_old)
421 new_ind(1:n_old) = grp%ind(1:n_old)
423 CALL move_alloc(new_dist, grp%dist)
424 CALL move_alloc(new_ind, grp%ind)
426 ALLOCATE (grp%dist(4, new_cap))
427 ALLOCATE (grp%ind(new_cap))
444 TYPE(nnp_neighbor_workspace_type),
INTENT(INOUT) :: workspace
445 INTEGER,
INTENT(IN) :: n_needed
449 IF (workspace%cache_cap >= n_needed)
RETURN
451 new_cap = max(max(8, n_needed), int(workspace%cache_cap*1.5_dp) + 8)
453 IF (
ALLOCATED(workspace%fc_cache1))
DEALLOCATE (workspace%fc_cache1)
454 IF (
ALLOCATED(workspace%dfc_cache1))
DEALLOCATE (workspace%dfc_cache1)
455 IF (
ALLOCATED(workspace%fc_cache2))
DEALLOCATE (workspace%fc_cache2)
456 IF (
ALLOCATED(workspace%dfc_cache2))
DEALLOCATE (workspace%dfc_cache2)
457 ALLOCATE (workspace%fc_cache1(new_cap))
458 ALLOCATE (workspace%dfc_cache1(new_cap))
459 ALLOCATE (workspace%fc_cache2(new_cap))
460 ALLOCATE (workspace%dfc_cache2(new_cap))
461 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.