(git:be2ee82)
Loading...
Searching...
No Matches
dbt_array_list_methods.F
Go to the documentation of this file.
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: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Representation of arbitrary number of 1d integer arrays with arbitrary sizes.
10!> This is needed for generic handling of dimension-specific tensor quantities
11!> (such as block index).
12!> \author Patrick Seewald
13! **************************************************************************************************
15
16
17
20
21#include "../base/base_uses.f90"
22#if defined(__LIBXS)
23 USE libxs, ONLY: libxs_diff
24# define PURE_ARRAY_EQ
25#else
26# define PURE_ARRAY_EQ PURE
27#endif
28
29 IMPLICIT NONE
30 PRIVATE
31 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dbt_array_list_methods'
32
33 PUBLIC :: &
34 array_eq_i, &
35 array_list, &
41 get_arrays, &
48
50 INTEGER, DIMENSION(:), ALLOCATABLE :: col_data
51 INTEGER, DIMENSION(:), ALLOCATABLE :: ptr
52 END TYPE
53
54 INTERFACE get_ith_array
55 MODULE PROCEDURE allocate_and_get_ith_array
56 MODULE PROCEDURE get_ith_array
57 END INTERFACE
58
59CONTAINS
60
61! **************************************************************************************************
62!> \brief number of arrays stored in list
63!> \author Patrick Seewald
64! **************************************************************************************************
65 PURE FUNCTION number_of_arrays(list)
66 TYPE(array_list), INTENT(IN) :: list
67 INTEGER :: number_of_arrays
68
69 number_of_arrays = SIZE(list%ptr) - 1
70
71 END FUNCTION number_of_arrays
72
73! **************************************************************************************************
74!> \brief Get an element for each array.
75!> \param indices element index for each array
76!> \author Patrick Seewald
77! **************************************************************************************************
78 PURE FUNCTION get_array_elements(list, indices)
79 TYPE(array_list), INTENT(IN) :: list
80 INTEGER, DIMENSION(number_of_arrays(list)), INTENT(IN) :: indices
81 INTEGER, DIMENSION(number_of_arrays(list)) :: get_array_elements
82
83 INTEGER :: i, ind
84
85 DO i = 1, SIZE(indices)
86 ind = indices(i) + list%ptr(i) - 1
87 get_array_elements(i) = list%col_data(ind)
88 END DO
89
90 END FUNCTION get_array_elements
91
92! **************************************************************************************************
93!> \brief collects any number of arrays of different sizes into a single array (list%col_data),
94!> storing the indices that start a new array (list%ptr).
95!> \param list list of arrays
96!> \param ndata number of arrays
97!> \param data arrays 1 and 2
98!> \author Patrick Seewald
99! **************************************************************************************************
100 SUBROUTINE create_array_list(list, ndata, data_1, data_2, data_3, data_4)
101 TYPE(array_list), INTENT(OUT) :: list
102 INTEGER, INTENT(IN) :: ndata
103 INTEGER, DIMENSION(:), INTENT(IN), OPTIONAL :: data_1, data_2, data_3, data_4
104 INTEGER :: ptr, size_all
105
106 size_all = 0
107
108 IF (ndata >= 1) THEN
109 cpassert(PRESENT(data_1))
110 size_all = size_all + SIZE(data_1)
111 END IF
112 IF (ndata >= 2) THEN
113 cpassert(PRESENT(data_2))
114 size_all = size_all + SIZE(data_2)
115 END IF
116 IF (ndata >= 3) THEN
117 cpassert(PRESENT(data_3))
118 size_all = size_all + SIZE(data_3)
119 END IF
120 IF (ndata >= 4) THEN
121 cpassert(PRESENT(data_4))
122 size_all = size_all + SIZE(data_4)
123 END IF
124
125 ALLOCATE (list%ptr(ndata + 1))
126 ALLOCATE (list%col_data(size_all))
127
128 ptr = 1
129 list%ptr(1) = ptr
130
131 IF (ndata >= 1) THEN
132 list%col_data(ptr:ptr + SIZE(data_1) - 1) = data_1(:)
133 ptr = ptr + SIZE(data_1)
134 list%ptr(2) = ptr
135 END IF
136 IF (ndata >= 2) THEN
137 list%col_data(ptr:ptr + SIZE(data_2) - 1) = data_2(:)
138 ptr = ptr + SIZE(data_2)
139 list%ptr(3) = ptr
140 END IF
141 IF (ndata >= 3) THEN
142 list%col_data(ptr:ptr + SIZE(data_3) - 1) = data_3(:)
143 ptr = ptr + SIZE(data_3)
144 list%ptr(4) = ptr
145 END IF
146 IF (ndata >= 4) THEN
147 list%col_data(ptr:ptr + SIZE(data_4) - 1) = data_4(:)
148 ptr = ptr + SIZE(data_4)
149 list%ptr(5) = ptr
150 END IF
151
152 END SUBROUTINE
153
154! **************************************************************************************************
155!> \brief extract a subset of arrays
156!> \param list list of arrays
157!> \param i_selected array numbers to retrieve
158!> \author Patrick Seewald
159! **************************************************************************************************
160 FUNCTION array_sublist(list, i_selected)
161 TYPE(array_list), INTENT(IN) :: list
162 INTEGER, DIMENSION(:), INTENT(IN) :: i_selected
164 INTEGER :: ndata
165 INTEGER, ALLOCATABLE, DIMENSION(:) :: data_1, data_2, data_3, data_4
166
167 ndata = SIZE(i_selected)
168
169 IF (ndata == 1) THEN
170 CALL get_arrays(list, data_1, i_selected=i_selected)
171 CALL create_array_list(array_sublist, ndata, data_1)
172 END IF
173 IF (ndata == 2) THEN
174 CALL get_arrays(list, data_1, data_2, i_selected=i_selected)
175 CALL create_array_list(array_sublist, ndata, data_1, data_2)
176 END IF
177 IF (ndata == 3) THEN
178 CALL get_arrays(list, data_1, data_2, data_3, i_selected=i_selected)
179 CALL create_array_list(array_sublist, ndata, data_1, data_2, data_3)
180 END IF
181 IF (ndata == 4) THEN
182 CALL get_arrays(list, data_1, data_2, data_3, data_4, i_selected=i_selected)
183 CALL create_array_list(array_sublist, ndata, data_1, data_2, data_3, data_4)
184 END IF
185 END FUNCTION
186
187! **************************************************************************************************
188!> \brief destroy array list.
189!> \author Patrick Seewald
190! **************************************************************************************************
191 SUBROUTINE destroy_array_list(list)
192 TYPE(array_list), INTENT(INOUT) :: list
193
194 DEALLOCATE (list%ptr, list%col_data)
195 END SUBROUTINE
196
197! **************************************************************************************************
198!> \brief Get all arrays contained in list
199!> \param data arrays 1 and 2
200!> \param i_selected array numbers to retrieve (if not present, all arrays are returned)
201!> \author Patrick Seewald
202! **************************************************************************************************
203 SUBROUTINE get_arrays(list, data_1, data_2, data_3, data_4, i_selected)
204 !! Get all arrays contained in list
205 TYPE(array_list), INTENT(IN) :: list
206 INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(OUT), &
207 OPTIONAL :: data_1, data_2, data_3, data_4
208 INTEGER, DIMENSION(:), INTENT(IN), &
209 OPTIONAL :: i_selected
210 INTEGER :: i, ndata
211 INTEGER, DIMENSION(number_of_arrays(list)) :: o
212
213 o(:) = 0
214 IF (PRESENT(i_selected)) THEN
215 ndata = SIZE(i_selected)
216 o(1:ndata) = i_selected(:)
217 ELSE
218 ndata = number_of_arrays(list)
219 o(1:ndata) = (/(i, i=1, ndata)/)
220 END IF
221
222 associate(ptr => list%ptr, col_data => list%col_data)
223 IF (ndata > 0) THEN
224 ALLOCATE (data_1, source=col_data(ptr(o(1)):ptr(o(1) + 1) - 1))
225 END IF
226 IF (ndata > 1) THEN
227 ALLOCATE (data_2, source=col_data(ptr(o(2)):ptr(o(2) + 1) - 1))
228 END IF
229 IF (ndata > 2) THEN
230 ALLOCATE (data_3, source=col_data(ptr(o(3)):ptr(o(3) + 1) - 1))
231 END IF
232 IF (ndata > 3) THEN
233 ALLOCATE (data_4, source=col_data(ptr(o(4)):ptr(o(4) + 1) - 1))
234 END IF
235 END associate
236
237 END SUBROUTINE get_arrays
238
239! **************************************************************************************************
240!> \brief get ith array
241!> \author Patrick Seewald
242! **************************************************************************************************
243 SUBROUTINE get_ith_array(list, i, array_size, array)
244 TYPE(array_list), INTENT(IN) :: list
245 INTEGER, INTENT(IN) :: i
246 INTEGER, INTENT(IN) :: array_size
247 INTEGER, DIMENSION(array_size), INTENT(OUT) :: array
248
249 associate(ptr => list%ptr, col_data => list%col_data)
250 cpassert(i <= number_of_arrays(list))
251
252 array(:) = col_data(ptr(i):ptr(i + 1) - 1)
253
254 END associate
255
256 END SUBROUTINE
257
258! **************************************************************************************************
259!> \brief get ith array
260!> \author Patrick Seewald
261! **************************************************************************************************
262 SUBROUTINE allocate_and_get_ith_array(list, i, array)
263 TYPE(array_list), INTENT(IN) :: list
264 INTEGER, INTENT(IN) :: i
265 INTEGER, DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: array
266
267 associate(ptr => list%ptr, col_data => list%col_data)
268 cpassert(i <= number_of_arrays(list))
269
270 ALLOCATE (array, source=col_data(ptr(i):ptr(i + 1) - 1))
271 END associate
272 END SUBROUTINE
273
274! **************************************************************************************************
275!> \brief sizes of arrays stored in list
276!> \author Patrick Seewald
277! **************************************************************************************************
278 FUNCTION sizes_of_arrays(list)
279 TYPE(array_list), INTENT(IN) :: list
280 INTEGER, ALLOCATABLE, DIMENSION(:) :: sizes_of_arrays
281
282 INTEGER :: i_data, num_data
283
284 num_data = number_of_arrays(list)
285 ALLOCATE (sizes_of_arrays(num_data))
286 DO i_data = 1, num_data
287 sizes_of_arrays(i_data) = list%ptr(i_data + 1) - list%ptr(i_data)
288 END DO
289 END FUNCTION sizes_of_arrays
290
291! **************************************************************************************************
292!> \brief sum of all elements for each array stored in list
293!> \author Patrick Seewald
294! **************************************************************************************************
295 FUNCTION sum_of_arrays(list)
296 TYPE(array_list), INTENT(IN) :: list
297 INTEGER, ALLOCATABLE, DIMENSION(:) :: sum_of_arrays
298
299 INTEGER :: i_data, num_data
300
301 num_data = number_of_arrays(list)
302 ALLOCATE (sum_of_arrays(num_data))
303 DO i_data = 1, num_data
304 sum_of_arrays(i_data) = sum(list%col_data(list%ptr(i_data):list%ptr(i_data + 1) - 1))
305 END DO
306
307 END FUNCTION sum_of_arrays
308
309! **************************************************************************************************
310!> \brief partial sums of array elements.
311!> \author Patrick Seewald
312! **************************************************************************************************
313 SUBROUTINE array_offsets(list_in, list_out)
314 TYPE(array_list), INTENT(IN) :: list_in
315 TYPE(array_list), INTENT(OUT) :: list_out
316
317 INTEGER :: i_data, i_ptr, num_data, partial_sum
318
319 num_data = number_of_arrays(list_in)
320 ALLOCATE (list_out%ptr, source=list_in%ptr)
321 ALLOCATE (list_out%col_data(SIZE(list_in%col_data)))
322 DO i_data = 1, num_data
323 partial_sum = 1
324 DO i_ptr = list_out%ptr(i_data), list_out%ptr(i_data + 1) - 1
325 list_out%col_data(i_ptr) = partial_sum
326 partial_sum = partial_sum + list_in%col_data(i_ptr)
327 END DO
328 END DO
329 END SUBROUTINE
330
331! **************************************************************************************************
332!> \brief reorder array list.
333!> \author Patrick Seewald
334! **************************************************************************************************
335 SUBROUTINE reorder_arrays(list_in, list_out, order)
336 TYPE(array_list), INTENT(IN) :: list_in
337 TYPE(array_list), INTENT(OUT) :: list_out
338 INTEGER, ALLOCATABLE, DIMENSION(:) :: data_1, data_2, data_3, data_4
339 INTEGER, DIMENSION(number_of_arrays(list_in)), &
340 INTENT(IN) :: order
341
342 IF (number_of_arrays(list_in) == 2) THEN
343 CALL get_arrays(list_in, data_1, data_2, i_selected=dbt_inverse_order(order))
344 CALL create_array_list(list_out, number_of_arrays(list_in), &
345 data_1, data_2)
346 END IF
347 IF (number_of_arrays(list_in) == 3) THEN
348 CALL get_arrays(list_in, data_1, data_2, data_3, i_selected=dbt_inverse_order(order))
349 CALL create_array_list(list_out, number_of_arrays(list_in), &
350 data_1, data_2, data_3)
351 END IF
352 IF (number_of_arrays(list_in) == 4) THEN
353 CALL get_arrays(list_in, data_1, data_2, data_3, data_4, i_selected=dbt_inverse_order(order))
354 CALL create_array_list(list_out, number_of_arrays(list_in), &
355 data_1, data_2, data_3, data_4)
356 END IF
357
358 END SUBROUTINE
359
360! **************************************************************************************************
361!> \brief check whether two array lists are equal
362!> \author Patrick Seewald
363! **************************************************************************************************
364 FUNCTION check_equal(list1, list2)
365 TYPE(array_list), INTENT(IN) :: list1, list2
366 LOGICAL :: check_equal
367
368 check_equal = array_eq_i(list1%col_data, list2%col_data) .AND. array_eq_i(list1%ptr, list2%ptr)
369 END FUNCTION
370
371! **************************************************************************************************
372!> \brief check whether two arrays are equal
373!> \author Patrick Seewald
374! **************************************************************************************************
375 pure_array_eq FUNCTION array_eq_i(arr1, arr2)
376 INTEGER, INTENT(IN), DIMENSION(:) :: arr1
377 INTEGER, INTENT(IN), DIMENSION(:) :: arr2
378 LOGICAL :: array_eq_i
379
380#if defined(__LIBXS)
381 array_eq_i = .NOT. libxs_diff(arr1, arr2)
382#else
383 array_eq_i = .false.
384 IF (SIZE(arr1) == SIZE(arr2)) array_eq_i = all(arr1 == arr2)
385#endif
386 END FUNCTION
387
388END MODULE dbt_array_list_methods
Wrapper for allocating, copying and reshaping arrays.
Representation of arbitrary number of 1d integer arrays with arbitrary sizes. This is needed for gene...
integer function, dimension(:), allocatable, public sum_of_arrays(list)
sum of all elements for each array stored in list
subroutine, public get_arrays(list, data_1, data_2, data_3, data_4, i_selected)
Get all arrays contained in list.
subroutine, public create_array_list(list, ndata, data_1, data_2, data_3, data_4)
collects any number of arrays of different sizes into a single array (listcol_data),...
subroutine, public destroy_array_list(list)
destroy array list.
integer function, dimension(:), allocatable, public sizes_of_arrays(list)
sizes of arrays stored in list
pure integer function, public number_of_arrays(list)
number of arrays stored in list
subroutine, public array_offsets(list_in, list_out)
partial sums of array elements.
pure integer function, dimension(number_of_arrays(list)), public get_array_elements(list, indices)
Get an element for each array.
type(array_list) function, public array_sublist(list, i_selected)
extract a subset of arrays
subroutine, public reorder_arrays(list_in, list_out, order)
reorder array list.
logical function, public check_equal(list1, list2)
check whether two array lists are equal
tensor index and mapping to DBM index
Definition dbt_index.F:12
pure integer function, dimension(size(order)), public dbt_inverse_order(order)
Invert order.
Definition dbt_index.F:410
An array-based list which grows on demand. When the internal array is full, a new array of twice the ...
Definition list.F:24