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