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