(git:374b731)
Loading...
Searching...
No Matches
qs_fb_matrix_data_types.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
9
10 USE kinds, ONLY: dp,&
11 int_8
27#include "./base/base_uses.f90"
28
29 IMPLICIT NONE
30
31 PRIVATE
32
33 ! public types
34 PUBLIC :: fb_matrix_data_obj
35
36 ! public methods
37 !API
38 PUBLIC :: fb_matrix_data_add, &
44
45 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_fb_matrix_data_types'
46
47 ! Parameters related to automatic resizing of matrix_data:
48 INTEGER, PARAMETER, PRIVATE :: EXPAND_FACTOR = 2
49
50! **************************************************************************************************
51!> \brief data type for storing a list of matrix blocks
52!> \param nmax : maximum number of blocks can be stored
53!> \param nblks : number of blocks currently stored
54!> \param nencode : integer used to encode global block coordinate (row, col)
55!> into a single combined integer
56!> \param ind : hash table maping the global combined index of the blocks
57!> to the location in the data area
58!> \param blks : data area, well the matrix elements are actuaally stored
59!> \param lds : leading dimensions of each block
60!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
61! **************************************************************************************************
62 TYPE fb_matrix_data_data
63 INTEGER :: nmax
64 INTEGER :: nblks
65 INTEGER :: nencode
66 TYPE(fb_hash_table_obj) :: ind
67 TYPE(fb_buffer_d_obj) :: blks
68 INTEGER, DIMENSION(:), POINTER :: lds => null()
69 END TYPE fb_matrix_data_data
70
71! **************************************************************************************************
72!> \brief the object container which allows for the creation of an array
73!> of pointers to fb_matrix_data objects
74!> \param obj : pointer to the fb_matrix_data object
75!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
76! **************************************************************************************************
78 TYPE(fb_matrix_data_data), POINTER, PRIVATE :: obj => null()
79 END TYPE fb_matrix_data_obj
80
81CONTAINS
82
83! **************************************************************************************************
84!> \brief Add a matrix block to a fb_matrix_data object
85!> \param matrix_data : the fb_matrix_data object
86!> \param row : block row index of the matrix block
87!> \param col : block col index of the matrix block
88!> \param blk : the matrix block to add
89!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
90! **************************************************************************************************
91 SUBROUTINE fb_matrix_data_add(matrix_data, row, col, blk)
92 TYPE(fb_matrix_data_obj), INTENT(INOUT) :: matrix_data
93 INTEGER, INTENT(IN) :: row, col
94 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: blk
95
96 INTEGER :: existing_ii, ii, ncols, nrows, old_nblks
97 INTEGER(KIND=int_8) :: pair_ind
98 INTEGER, DIMENSION(:), POINTER :: new_lds
99 LOGICAL :: check_ok, found
100
101 check_ok = fb_matrix_data_has_data(matrix_data)
102 cpassert(check_ok)
103 NULLIFY (new_lds)
104 nrows = SIZE(blk, 1)
105 ncols = SIZE(blk, 2)
106 ! first check if the block already exists in matrix_data
107 pair_ind = fb_matrix_data_encode_pair(row, col, matrix_data%obj%nencode)
108 CALL fb_hash_table_get(matrix_data%obj%ind, pair_ind, existing_ii, found)
109 IF (found) THEN
110 CALL fb_buffer_replace(matrix_data%obj%blks, existing_ii, reshape(blk, (/nrows*ncols/)))
111 ELSE
112 old_nblks = matrix_data%obj%nblks
113 matrix_data%obj%nblks = old_nblks + 1
114 ii = matrix_data%obj%nblks
115 ! resize lds if necessary
116 IF (SIZE(matrix_data%obj%lds) .LT. ii) THEN
117 ALLOCATE (new_lds(ii*expand_factor))
118 new_lds = 0
119 new_lds(1:old_nblks) = matrix_data%obj%lds(1:old_nblks)
120 DEALLOCATE (matrix_data%obj%lds)
121 matrix_data%obj%lds => new_lds
122 END IF
123 ! add data block
124 matrix_data%obj%lds(ii) = nrows
125 CALL fb_buffer_add(matrix_data%obj%blks, reshape(blk, (/nrows*ncols/)))
126 ! record blk index in the index table
127 CALL fb_hash_table_add(matrix_data%obj%ind, pair_ind, ii)
128 END IF
129 END SUBROUTINE fb_matrix_data_add
130
131! **************************************************************************************************
132!> \brief Associates one fb_matrix_data object to another
133!> \param a : the fb_matrix_data object to be associated
134!> \param b : the fb_matrix_data object that a is to be associated to
135!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
136! **************************************************************************************************
137 SUBROUTINE fb_matrix_data_associate(a, b)
138 TYPE(fb_matrix_data_obj), INTENT(OUT) :: a
139 TYPE(fb_matrix_data_obj), INTENT(IN) :: b
140
141 a%obj => b%obj
142 END SUBROUTINE fb_matrix_data_associate
143
144! **************************************************************************************************
145!> \brief Creates and initialises an empty fb_matrix_data object of a given size
146!> \param matrix_data : the fb_matrix_data object, its content must be NULL
147!> and cannot be UNDEFINED
148!> \param nmax : max number of matrix blks can be stored
149!> \param nencode ...
150!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
151! **************************************************************************************************
152 SUBROUTINE fb_matrix_data_create(matrix_data, nmax, nencode)
153 TYPE(fb_matrix_data_obj), INTENT(OUT) :: matrix_data
154 INTEGER, INTENT(IN) :: nmax, nencode
155
156 NULLIFY (matrix_data%obj)
157 ALLOCATE (matrix_data%obj)
158 CALL fb_hash_table_nullify(matrix_data%obj%ind)
159 CALL fb_buffer_nullify(matrix_data%obj%blks)
160 NULLIFY (matrix_data%obj%lds)
161 matrix_data%obj%nmax = 0
162 matrix_data%obj%nblks = 0
163 matrix_data%obj%nencode = nencode
164 CALL fb_matrix_data_init(matrix_data=matrix_data, &
165 nmax=nmax, &
166 nencode=nencode)
167 ! book keeping stuff
168 END SUBROUTINE fb_matrix_data_create
169
170! **************************************************************************************************
171!> \brief retrieve a matrix block from a matrix_data object
172!> \param matrix_data : the fb_matrix_data object
173!> \param row : row index
174!> \param col : col index
175!> \param blk_p : pointer to the block in the fb_matrix_data object
176!> \param found : if the requested block exists in the fb_matrix_data
177!> object
178!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
179! **************************************************************************************************
180 SUBROUTINE fb_matrix_data_get(matrix_data, row, col, blk_p, found)
181 TYPE(fb_matrix_data_obj), INTENT(IN) :: matrix_data
182 INTEGER, INTENT(IN) :: row, col
183 REAL(kind=dp), DIMENSION(:, :), POINTER :: blk_p
184 LOGICAL, INTENT(OUT) :: found
185
186 INTEGER :: ind_in_blks
187 INTEGER(KIND=int_8) :: pair_ind
188 LOGICAL :: check_ok
189
190 check_ok = fb_matrix_data_has_data(matrix_data)
191 cpassert(check_ok)
192 pair_ind = fb_matrix_data_encode_pair(row, col, matrix_data%obj%nencode)
193 CALL fb_hash_table_get(matrix_data%obj%ind, pair_ind, ind_in_blks, found)
194 IF (found) THEN
195 CALL fb_buffer_get(buffer=matrix_data%obj%blks, &
196 i_slice=ind_in_blks, &
197 data_2d=blk_p, &
198 data_2d_ld=matrix_data%obj%lds(ind_in_blks))
199 ELSE
200 NULLIFY (blk_p)
201 END IF
202 END SUBROUTINE fb_matrix_data_get
203
204! **************************************************************************************************
205!> \brief check if the object has data associated to it
206!> \param matrix_data : the fb_matrix_data object in question
207!> \return : true if matrix_data%obj is associated, false otherwise
208!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
209! **************************************************************************************************
210 PURE FUNCTION fb_matrix_data_has_data(matrix_data) RESULT(res)
211 TYPE(fb_matrix_data_obj), INTENT(IN) :: matrix_data
212 LOGICAL :: res
213
214 res = ASSOCIATED(matrix_data%obj)
215 END FUNCTION fb_matrix_data_has_data
216
217! **************************************************************************************************
218!> \brief Initialises a fb_matrix_data object of a given size
219!> \param matrix_data : the fb_matrix_data object, its content must be NULL
220!> and cannot be UNDEFINED
221!> \param nmax : max number of matrix blocks can be stored, default is
222!> to use the existing number of blocks in matrix_data
223!> \param nencode : integer used to incode (row, col) to a single combined
224!> index
225!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
226! **************************************************************************************************
227 SUBROUTINE fb_matrix_data_init(matrix_data, nmax, nencode)
228 TYPE(fb_matrix_data_obj), INTENT(INOUT) :: matrix_data
229 INTEGER, INTENT(IN), OPTIONAL :: nmax, nencode
230
231 INTEGER :: my_nmax
232 LOGICAL :: check_ok
233
234 check_ok = fb_matrix_data_has_data(matrix_data)
235 cpassert(check_ok)
236 my_nmax = matrix_data%obj%nmax
237 IF (PRESENT(nmax)) my_nmax = nmax
238 my_nmax = max(my_nmax, 1)
239 IF (fb_hash_table_has_data(matrix_data%obj%ind)) THEN
240 CALL fb_hash_table_release(matrix_data%obj%ind)
241 END IF
242 CALL fb_hash_table_create(matrix_data%obj%ind, my_nmax)
243 IF (fb_buffer_has_data(matrix_data%obj%blks)) THEN
244 CALL fb_buffer_release(matrix_data%obj%blks)
245 END IF
246 CALL fb_buffer_create(buffer=matrix_data%obj%blks)
247 IF (ASSOCIATED(matrix_data%obj%lds)) THEN
248 DEALLOCATE (matrix_data%obj%lds)
249 END IF
250 ALLOCATE (matrix_data%obj%lds(0))
251 matrix_data%obj%nblks = 0
252 IF (PRESENT(nencode)) matrix_data%obj%nencode = nencode
253 END SUBROUTINE fb_matrix_data_init
254
255! **************************************************************************************************
256!> \brief Nullifies a fb_matrix_data object
257!> \param matrix_data : the fb_matrix_data object
258!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
259! **************************************************************************************************
260 PURE SUBROUTINE fb_matrix_data_nullify(matrix_data)
261 TYPE(fb_matrix_data_obj), INTENT(INOUT) :: matrix_data
262
263 NULLIFY (matrix_data%obj)
264 END SUBROUTINE fb_matrix_data_nullify
265
266! **************************************************************************************************
267!> \brief releases given object
268!> \param matrix_data : the fb_matrix_data object in question
269!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
270! **************************************************************************************************
271 SUBROUTINE fb_matrix_data_release(matrix_data)
272 TYPE(fb_matrix_data_obj), INTENT(INOUT) :: matrix_data
273
274 IF (ASSOCIATED(matrix_data%obj)) THEN
275 IF (fb_hash_table_has_data(matrix_data%obj%ind)) THEN
276 CALL fb_hash_table_release(matrix_data%obj%ind)
277 END IF
278 IF (fb_buffer_has_data(matrix_data%obj%blks)) THEN
279 CALL fb_buffer_release(matrix_data%obj%blks)
280 END IF
281 IF (ASSOCIATED(matrix_data%obj%lds)) THEN
282 DEALLOCATE (matrix_data%obj%lds)
283 END IF
284 DEALLOCATE (matrix_data%obj)
285 END IF
286 NULLIFY (matrix_data%obj)
287 END SUBROUTINE fb_matrix_data_release
288
289! **************************************************************************************************
290!> \brief outputs the current information about fb_matrix_data object
291!> \param matrix_data : the fb_matrix_data object
292!> \param nmax : outputs fb_matrix_data%obj%nmax
293!> \param nblks : outputs fb_matrix_data%obj%nblks
294!> \param nencode : outputs fb_matrix_data%obj%nencode
295!> \param blk_sizes : blk_sizes(ii,jj) gives size of jj-th dim of the
296!> ii-th block stored
297!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
298! **************************************************************************************************
299 SUBROUTINE fb_matrix_data_status(matrix_data, nmax, nblks, nencode, blk_sizes)
300 TYPE(fb_matrix_data_obj), INTENT(INOUT) :: matrix_data
301 INTEGER, INTENT(OUT), OPTIONAL :: nmax, nblks, nencode
302 INTEGER, DIMENSION(:, :), INTENT(OUT), OPTIONAL :: blk_sizes
303
304 INTEGER :: ii
305 INTEGER, ALLOCATABLE, DIMENSION(:) :: buffer_sizes
306 LOGICAL :: check_ok
307
308 check_ok = fb_matrix_data_has_data(matrix_data)
309 cpassert(check_ok)
310 IF (PRESENT(nmax)) nmax = matrix_data%obj%nmax
311 IF (PRESENT(nblks)) nblks = matrix_data%obj%nblks
312 IF (PRESENT(nencode)) nencode = matrix_data%obj%nencode
313 IF (PRESENT(blk_sizes)) THEN
314 check_ok = (SIZE(blk_sizes, 1) .GE. matrix_data%obj%nblks .AND. &
315 SIZE(blk_sizes, 2) .GE. 2)
316 cpassert(check_ok)
317 blk_sizes(:, :) = 0
318 ALLOCATE (buffer_sizes(matrix_data%obj%nblks))
319 CALL fb_buffer_get(buffer=matrix_data%obj%blks, &
320 sizes=buffer_sizes)
321 DO ii = 1, matrix_data%obj%nblks
322 blk_sizes(ii, 1) = matrix_data%obj%lds(ii)
323 blk_sizes(ii, 2) = buffer_sizes(ii)/matrix_data%obj%lds(ii)
324 END DO
325 DEALLOCATE (buffer_sizes)
326 END IF
327 END SUBROUTINE fb_matrix_data_status
328
329! **************************************************************************************************
330!> \brief Encodes (row, col) index pair into a single combined index
331!> \param row : row index (assume to start counting from 1)
332!> \param col : col index (assume to start counting from 1)
333!> \param nencode : integer used for encoding
334!> \return : the returned value
335!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
336! **************************************************************************************************
337 PURE FUNCTION fb_matrix_data_encode_pair(row, col, nencode) &
338 result(pair_ind)
339 INTEGER, INTENT(IN) :: row, col, nencode
340 INTEGER(KIND=int_8) :: pair_ind
341
342 INTEGER(KIND=int_8) :: col_8, nencode_8, row_8
343
344 row_8 = int(row, int_8)
345 col_8 = int(col, int_8)
346 nencode_8 = int(nencode, int_8)
347 pair_ind = (row_8 - 1_int_8)*nencode_8 + (col_8 - 1_int_8) + 1
348 END FUNCTION fb_matrix_data_encode_pair
349
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
A simple hash table of integer keys, using hash function: H(k) = (k*p) mod n + 1 where: k = key p = a...
pure logical function, public fb_hash_table_has_data(hash_table)
check if the object has data associated to it
recursive subroutine, public fb_hash_table_add(hash_table, key, val)
Add element to a hash table, auto resize if necessary.
subroutine, public fb_hash_table_release(hash_table)
releases given object
subroutine, public fb_hash_table_get(hash_table, key, val, found)
Retrieve value from a key from a hash table.
subroutine, public fb_hash_table_create(hash_table, nmax)
Creates and initialises an empty fb_hash_table object.
pure subroutine, public fb_hash_table_nullify(hash_table)
Nullifies a fb_hash_table object.
pure logical function, public fb_matrix_data_has_data(matrix_data)
check if the object has data associated to it
subroutine, public fb_matrix_data_add(matrix_data, row, col, blk)
Add a matrix block to a fb_matrix_data object.
subroutine, public fb_matrix_data_get(matrix_data, row, col, blk_p, found)
retrieve a matrix block from a matrix_data object
subroutine, public fb_matrix_data_create(matrix_data, nmax, nencode)
Creates and initialises an empty fb_matrix_data object of a given size.
pure subroutine, public fb_matrix_data_nullify(matrix_data)
Nullifies a fb_matrix_data object.
subroutine, public fb_matrix_data_release(matrix_data)
releases given object
object/pointer wrapper for fb_buffer object
the object container which allows for the creation of an array of pointers to fb_hash_table objects
the object container which allows for the creation of an array of pointers to fb_matrix_data objects