Line data Source code
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 : MODULE qs_fb_buffer_types
9 :
10 : USE kinds, ONLY: dp
11 : #include "./base/base_uses.f90"
12 :
13 : IMPLICIT NONE
14 :
15 : PRIVATE
16 :
17 : ! public types
18 : PUBLIC :: fb_buffer_d_obj
19 :
20 : ! public methods
21 : !API
22 : PUBLIC :: fb_buffer_add, &
23 : fb_buffer_create, &
24 : fb_buffer_get, &
25 : fb_buffer_has_data, &
26 : fb_buffer_release, &
27 : fb_buffer_nullify, &
28 : fb_buffer_replace
29 :
30 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_fb_buffer_types'
31 :
32 : ! **********************************************************************
33 : !> \brief data for the fb_buffer object (integer)
34 : !> \param n : number of data slices in the buffer
35 : !> \param disps : displacement in data array of each slice, it contains
36 : !> one more element at the end recording the total
37 : !> size of the current data, which is the same as the
38 : !> displacement for the new data to be added
39 : !> \param data_1d : where all of the slices are stored
40 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
41 : ! **********************************************************************
42 : TYPE fb_buffer_i_data
43 : INTEGER :: n = -1
44 : INTEGER, DIMENSION(:), POINTER :: disps => NULL()
45 : INTEGER, DIMENSION(:), POINTER :: data_1d => NULL()
46 : END TYPE fb_buffer_i_data
47 :
48 : ! **********************************************************************
49 : !> \brief object/pointer wrapper for fb_buffer object
50 : !> \param obj : pointer to fb_buffer data
51 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
52 : ! **********************************************************************
53 : TYPE fb_buffer_i_obj
54 : TYPE(fb_buffer_i_data), POINTER, PRIVATE :: obj => NULL()
55 : END TYPE fb_buffer_i_obj
56 :
57 : ! **********************************************************************
58 : !> \brief data for the fb_buffer object (real, double)
59 : !> \param n : number of data slices in the buffer
60 : !> \param disps : displacement in data array of each slice, it contains
61 : !> one more element at the end recording the total
62 : !> size of the current data, which is the same as the
63 : !> displacement for the new data to be added
64 : !> \param data_1d : where all of the slices are stored
65 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
66 : ! **********************************************************************
67 : TYPE fb_buffer_d_data
68 : INTEGER :: n = -1
69 : INTEGER, DIMENSION(:), POINTER :: disps => NULL()
70 : REAL(KIND=dp), DIMENSION(:), POINTER :: data_1d => NULL()
71 : END TYPE fb_buffer_d_data
72 :
73 : ! **********************************************************************
74 : !> \brief object/pointer wrapper for fb_buffer object
75 : !> \param obj : pointer to fb_buffer data
76 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
77 : ! **********************************************************************
78 : TYPE fb_buffer_d_obj
79 : TYPE(fb_buffer_d_data), POINTER, PRIVATE :: obj => NULL()
80 : END TYPE fb_buffer_d_obj
81 :
82 : ! method overload interfaces
83 : INTERFACE fb_buffer_add
84 : MODULE PROCEDURE fb_buffer_i_add
85 : MODULE PROCEDURE fb_buffer_d_add
86 : END INTERFACE fb_buffer_add
87 :
88 : INTERFACE fb_buffer_create
89 : MODULE PROCEDURE fb_buffer_i_create
90 : MODULE PROCEDURE fb_buffer_d_create
91 : END INTERFACE fb_buffer_create
92 :
93 : INTERFACE fb_buffer_calc_disps
94 : MODULE PROCEDURE fb_buffer_i_calc_disps
95 : MODULE PROCEDURE fb_buffer_d_calc_disps
96 : END INTERFACE fb_buffer_calc_disps
97 :
98 : INTERFACE fb_buffer_calc_sizes
99 : MODULE PROCEDURE fb_buffer_i_calc_sizes
100 : MODULE PROCEDURE fb_buffer_d_calc_sizes
101 : END INTERFACE fb_buffer_calc_sizes
102 :
103 : INTERFACE fb_buffer_get
104 : MODULE PROCEDURE fb_buffer_i_get
105 : MODULE PROCEDURE fb_buffer_d_get
106 : END INTERFACE fb_buffer_get
107 :
108 : INTERFACE fb_buffer_has_data
109 : MODULE PROCEDURE fb_buffer_i_has_data
110 : MODULE PROCEDURE fb_buffer_d_has_data
111 : END INTERFACE fb_buffer_has_data
112 :
113 : INTERFACE fb_buffer_release
114 : MODULE PROCEDURE fb_buffer_i_release
115 : MODULE PROCEDURE fb_buffer_d_release
116 : END INTERFACE fb_buffer_release
117 :
118 : INTERFACE fb_buffer_nullify
119 : MODULE PROCEDURE fb_buffer_i_nullify
120 : MODULE PROCEDURE fb_buffer_d_nullify
121 : END INTERFACE fb_buffer_nullify
122 :
123 : INTERFACE fb_buffer_replace
124 : MODULE PROCEDURE fb_buffer_i_replace
125 : MODULE PROCEDURE fb_buffer_d_replace
126 : END INTERFACE fb_buffer_replace
127 :
128 : CONTAINS
129 :
130 : ! INTEGER VERSION
131 :
132 : ! **************************************************************************************************
133 : !> \brief releases the given fb_buffer
134 : !> \param buffer : the fb_bffer object
135 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
136 : ! **************************************************************************************************
137 0 : SUBROUTINE fb_buffer_i_release(buffer)
138 : TYPE(fb_buffer_i_obj), INTENT(INOUT) :: buffer
139 :
140 0 : IF (ASSOCIATED(buffer%obj)) THEN
141 0 : IF (ASSOCIATED(buffer%obj%data_1d)) THEN
142 0 : DEALLOCATE (buffer%obj%data_1d)
143 : END IF
144 0 : IF (ASSOCIATED(buffer%obj%disps)) THEN
145 0 : DEALLOCATE (buffer%obj%disps)
146 : END IF
147 0 : DEALLOCATE (buffer%obj)
148 : ELSE
149 0 : NULLIFY (buffer%obj)
150 : END IF
151 0 : END SUBROUTINE fb_buffer_i_release
152 :
153 : ! **************************************************************************************************
154 : !> \brief nullify the given fb_buffer
155 : !> \param buffer : the fb_bffer object
156 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
157 : ! **************************************************************************************************
158 0 : SUBROUTINE fb_buffer_i_nullify(buffer)
159 : TYPE(fb_buffer_i_obj), INTENT(INOUT) :: buffer
160 :
161 0 : NULLIFY (buffer%obj)
162 0 : END SUBROUTINE fb_buffer_i_nullify
163 :
164 : ! **************************************************************************************************
165 : !> \brief check if an object as associated data
166 : !> \param buffer : fb_buffer object
167 : !> \return : .TRUE. if buffer has associated data
168 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
169 : ! **************************************************************************************************
170 0 : PURE FUNCTION fb_buffer_i_has_data(buffer) RESULT(res)
171 : TYPE(fb_buffer_i_obj), INTENT(IN) :: buffer
172 : LOGICAL :: res
173 :
174 0 : res = ASSOCIATED(buffer%obj)
175 0 : END FUNCTION fb_buffer_i_has_data
176 :
177 : ! **************************************************************************************************
178 : !> \brief creates a fb_buffer object
179 : !> \param buffer : fb_buffer object
180 : !> \param max_size : requested total size of the data array
181 : !> \param nslices : total number of slices for the data
182 : !> \param data_1d : the data to be copied to the buffer
183 : !> \param sizes : the size of the slices in the buffer
184 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
185 : ! **************************************************************************************************
186 0 : SUBROUTINE fb_buffer_i_create(buffer, &
187 : max_size, &
188 : nslices, &
189 0 : data_1d, &
190 0 : sizes)
191 : TYPE(fb_buffer_i_obj), INTENT(INOUT) :: buffer
192 : INTEGER, INTENT(IN), OPTIONAL :: max_size, nslices
193 : INTEGER, DIMENSION(:), INTENT(IN), OPTIONAL :: data_1d, sizes
194 :
195 : INTEGER :: my_max_size, my_ndata, my_nslices
196 : LOGICAL :: check_ok
197 :
198 : ! check optional input
199 :
200 0 : IF (PRESENT(data_1d)) THEN
201 0 : CPASSERT(PRESENT(sizes))
202 : END IF
203 :
204 0 : CPASSERT(.NOT. ASSOCIATED(buffer%obj))
205 0 : ALLOCATE (buffer%obj)
206 : ! work out the size of the data array and number of slices
207 0 : my_max_size = 0
208 0 : my_nslices = 0
209 0 : my_ndata = 0
210 : NULLIFY (buffer%obj%data_1d, &
211 : buffer%obj%disps)
212 : ! work out sizes
213 0 : IF (PRESENT(max_size)) my_max_size = max_size
214 0 : IF (PRESENT(nslices)) my_nslices = nslices
215 0 : IF (PRESENT(sizes)) THEN
216 0 : my_nslices = MIN(my_nslices, SIZE(sizes))
217 0 : my_ndata = SUM(sizes(1:my_nslices))
218 0 : my_max_size = MAX(my_max_size, my_ndata)
219 : END IF
220 : ! allocate the arrays
221 0 : ALLOCATE (buffer%obj%data_1d(my_max_size))
222 0 : ALLOCATE (buffer%obj%disps(my_nslices))
223 0 : buffer%obj%data_1d = 0
224 0 : buffer%obj%disps = 0
225 : ! set n for buffer before calc disps
226 0 : buffer%obj%n = my_nslices
227 : ! compute disps from sizes if required
228 0 : IF (PRESENT(sizes)) THEN
229 0 : CALL fb_buffer_calc_disps(buffer, sizes)
230 : END IF
231 : ! copy data
232 0 : IF (PRESENT(data_1d)) THEN
233 : check_ok = SIZE(data_1d) >= my_max_size .AND. &
234 0 : PRESENT(sizes)
235 0 : CPASSERT(check_ok)
236 0 : buffer%obj%data_1d(1:my_ndata) = data_1d(1:my_ndata)
237 : END IF
238 0 : END SUBROUTINE fb_buffer_i_create
239 :
240 : ! **************************************************************************************************
241 : !> \brief add some data into the buffer
242 : !> \param buffer : fb_buffer object
243 : !> \param data_1d : data to be copied into the object
244 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
245 : ! **************************************************************************************************
246 0 : SUBROUTINE fb_buffer_i_add(buffer, data_1d)
247 : TYPE(fb_buffer_i_obj), INTENT(INOUT) :: buffer
248 : INTEGER, DIMENSION(:), INTENT(IN) :: data_1d
249 :
250 : INTEGER :: new_data_size, new_n, this_size
251 0 : INTEGER, DIMENSION(:), POINTER :: new_data, new_disps
252 :
253 0 : NULLIFY (new_disps, new_data)
254 :
255 0 : this_size = SIZE(data_1d)
256 0 : new_n = buffer%obj%n + 1
257 0 : new_data_size = buffer%obj%disps(new_n) + this_size
258 : ! resize when needed
259 0 : IF (SIZE(buffer%obj%disps) < new_n + 1) THEN
260 0 : ALLOCATE (new_disps(new_n*2))
261 0 : new_disps = 0
262 0 : new_disps(1:buffer%obj%n + 1) = buffer%obj%disps(1:buffer%obj%n + 1)
263 0 : DEALLOCATE (buffer%obj%disps)
264 0 : buffer%obj%disps => new_disps
265 : END IF
266 0 : IF (SIZE(buffer%obj%data_1d) < new_data_size) THEN
267 0 : ALLOCATE (new_data(new_data_size*2))
268 0 : new_data = 0
269 : new_data(1:buffer%obj%disps(new_n)) = &
270 0 : buffer%obj%data_1d(1:buffer%obj%disps(new_n))
271 0 : DEALLOCATE (buffer%obj%data_1d)
272 0 : buffer%obj%data_1d => new_data
273 : END IF
274 : ! append to the buffer
275 0 : buffer%obj%disps(new_n + 1) = new_data_size
276 : buffer%obj%data_1d(buffer%obj%disps(new_n) + 1:new_data_size) = &
277 0 : data_1d(1:this_size)
278 0 : buffer%obj%n = new_n
279 0 : END SUBROUTINE fb_buffer_i_add
280 :
281 : ! **************************************************************************************************
282 : !> \brief compute the displacements of each slice in a data buffer from
283 : !> a given list of sizes of each slice
284 : !> \param buffer : fb_buffer object
285 : !> \param sizes : list of sizes of each slice on input
286 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
287 : ! **************************************************************************************************
288 0 : SUBROUTINE fb_buffer_i_calc_disps(buffer, sizes)
289 : TYPE(fb_buffer_i_obj), INTENT(INOUT) :: buffer
290 : INTEGER, DIMENSION(:), INTENT(IN) :: sizes
291 :
292 : INTEGER :: ii
293 :
294 0 : CPASSERT(SIZE(sizes) >= buffer%obj%n)
295 0 : buffer%obj%disps(1) = 0
296 0 : DO ii = 2, buffer%obj%n + 1
297 0 : buffer%obj%disps(ii) = buffer%obj%disps(ii - 1) + sizes(ii - 1)
298 : END DO
299 0 : END SUBROUTINE fb_buffer_i_calc_disps
300 :
301 : ! **************************************************************************************************
302 : !> \brief compute the sizes of each slice
303 : !> \param buffer : fb_buffer object
304 : !> \param sizes : list of sizes of each slice on output
305 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
306 : ! **************************************************************************************************
307 0 : SUBROUTINE fb_buffer_i_calc_sizes(buffer, sizes)
308 : TYPE(fb_buffer_i_obj), INTENT(IN) :: buffer
309 : INTEGER, DIMENSION(:), INTENT(OUT) :: sizes
310 :
311 : INTEGER :: ii
312 :
313 0 : CPASSERT(SIZE(sizes) >= buffer%obj%n)
314 0 : DO ii = 1, buffer%obj%n
315 0 : sizes(ii) = buffer%obj%disps(ii + 1) - buffer%obj%disps(ii)
316 : END DO
317 0 : END SUBROUTINE fb_buffer_i_calc_sizes
318 :
319 : ! **************************************************************************************************
320 : !> \brief get data from the fb_buffer object
321 : !> \param buffer : fb_buffer object
322 : !> \param i_slice : see data_1d, data_2d
323 : !> \param n : outputs number of slices in data array
324 : !> \param data_size : outputs the total size of stored data
325 : !> \param sizes : outputs sizes of the slices in data array
326 : !> \param disps : outputs displacements in the data array for each slice
327 : !> \param data_1d : if i_slice is present:
328 : !> returns pointer to the section of data array corresponding
329 : !> to i_slice-th slice
330 : !> else:
331 : !> return pointer to the entire non-empty part of the data array
332 : !> \param data_2d : similar to data_1d, but with the 1D data array reshaped to 2D
333 : !> works only with i_slice present
334 : !> \param data_2d_ld : leading dimension for data_2d for slice i_slice
335 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
336 : ! **************************************************************************************************
337 0 : SUBROUTINE fb_buffer_i_get(buffer, &
338 : i_slice, &
339 : n, &
340 : data_size, &
341 0 : sizes, &
342 0 : disps, &
343 : data_1d, &
344 : data_2d, &
345 : data_2d_ld)
346 : TYPE(fb_buffer_i_obj), INTENT(IN) :: buffer
347 : INTEGER, INTENT(IN), OPTIONAL :: i_slice
348 : INTEGER, INTENT(OUT), OPTIONAL :: n, data_size
349 : INTEGER, DIMENSION(:), INTENT(OUT), OPTIONAL :: sizes, disps
350 : INTEGER, DIMENSION(:), OPTIONAL, POINTER :: data_1d
351 : INTEGER, DIMENSION(:, :), OPTIONAL, POINTER :: data_2d
352 : INTEGER, INTENT(IN), OPTIONAL :: data_2d_ld
353 :
354 : INTEGER :: ncols, slice_size
355 :
356 0 : IF (PRESENT(n)) n = buffer%obj%n
357 0 : IF (PRESENT(data_size)) data_size = buffer%obj%disps(buffer%obj%n + 1)
358 0 : IF (PRESENT(sizes)) THEN
359 0 : CALL fb_buffer_calc_sizes(buffer, sizes)
360 : END IF
361 0 : IF (PRESENT(disps)) THEN
362 0 : CPASSERT(SIZE(disps) >= buffer%obj%n)
363 0 : disps(1:buffer%obj%n) = buffer%obj%disps(1:buffer%obj%n)
364 : END IF
365 0 : IF (PRESENT(data_1d)) THEN
366 0 : IF (PRESENT(i_slice)) THEN
367 0 : CPASSERT(i_slice <= buffer%obj%n)
368 : data_1d => buffer%obj%data_1d(buffer%obj%disps(i_slice) + 1: &
369 0 : buffer%obj%disps(i_slice + 1))
370 : ELSE
371 0 : data_1d => buffer%obj%data_1d(1:buffer%obj%disps(buffer%obj%n + 1))
372 : END IF
373 : END IF
374 0 : IF (PRESENT(data_2d)) THEN
375 0 : CPASSERT(PRESENT(data_2d_ld))
376 0 : CPASSERT(PRESENT(i_slice))
377 : ! cannot, or rather, it is inefficient to use reshape here, as
378 : ! a) reshape does not return a targeted array, so cannot
379 : ! associate pointer unless copied to a targeted array. b) in
380 : ! F2003 standard, pointers should rank remap automatically by
381 : ! association to a rank 1 array
382 0 : slice_size = buffer%obj%disps(i_slice + 1) - buffer%obj%disps(i_slice)
383 0 : ncols = slice_size/data_2d_ld
384 0 : CPASSERT(slice_size == data_2d_ld*ncols)
385 : data_2d(1:data_2d_ld, 1:ncols) => &
386 : buffer%obj%data_1d(buffer%obj%disps(i_slice) + 1: &
387 0 : buffer%obj%disps(i_slice + 1))
388 : END IF
389 0 : END SUBROUTINE fb_buffer_i_get
390 :
391 : ! **************************************************************************************************
392 : !> \brief replace a slice of the buffer, the replace data size must be
393 : !> identical to the original slice size
394 : !> \param buffer : fb_buffer object
395 : !> \param i_slice : the slice index in the buffer
396 : !> \param data_1d : the data to replace the slice
397 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
398 : ! **************************************************************************************************
399 0 : SUBROUTINE fb_buffer_i_replace(buffer, i_slice, data_1d)
400 : TYPE(fb_buffer_i_obj), INTENT(INOUT) :: buffer
401 : INTEGER, INTENT(IN) :: i_slice
402 : INTEGER, DIMENSION(:), INTENT(IN) :: data_1d
403 :
404 : INTEGER :: slice_size
405 :
406 0 : slice_size = buffer%obj%disps(i_slice + 1) - buffer%obj%disps(i_slice)
407 0 : CPASSERT(SIZE(data_1d) == slice_size)
408 : buffer%obj%data_1d(buffer%obj%disps(i_slice) + 1: &
409 0 : buffer%obj%disps(i_slice + 1)) = data_1d
410 0 : END SUBROUTINE fb_buffer_i_replace
411 :
412 : ! DOUBLE PRECISION VERSION
413 :
414 : ! **************************************************************************************************
415 : !> \brief releases the given fb_buffer
416 : !> \param buffer : the fb_bffer object
417 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
418 : ! **************************************************************************************************
419 48 : SUBROUTINE fb_buffer_d_release(buffer)
420 : TYPE(fb_buffer_d_obj), INTENT(INOUT) :: buffer
421 :
422 48 : IF (ASSOCIATED(buffer%obj)) THEN
423 48 : IF (ASSOCIATED(buffer%obj%data_1d)) THEN
424 48 : DEALLOCATE (buffer%obj%data_1d)
425 : END IF
426 48 : IF (ASSOCIATED(buffer%obj%disps)) THEN
427 48 : DEALLOCATE (buffer%obj%disps)
428 : END IF
429 48 : DEALLOCATE (buffer%obj)
430 : ELSE
431 0 : NULLIFY (buffer%obj)
432 : END IF
433 48 : END SUBROUTINE fb_buffer_d_release
434 :
435 : ! **************************************************************************************************
436 : !> \brief nullify the given fb_buffer
437 : !> \param buffer : the fb_bffer object
438 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
439 : ! **************************************************************************************************
440 48 : SUBROUTINE fb_buffer_d_nullify(buffer)
441 : TYPE(fb_buffer_d_obj), INTENT(INOUT) :: buffer
442 :
443 48 : NULLIFY (buffer%obj)
444 48 : END SUBROUTINE fb_buffer_d_nullify
445 :
446 : ! **************************************************************************************************
447 : !> \brief check if an object as associated data
448 : !> \param buffer : fb_buffer object
449 : !> \return : .TRUE. if buffer has associated data
450 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
451 : ! **************************************************************************************************
452 96 : PURE FUNCTION fb_buffer_d_has_data(buffer) RESULT(res)
453 : TYPE(fb_buffer_d_obj), INTENT(IN) :: buffer
454 : LOGICAL :: res
455 :
456 96 : res = ASSOCIATED(buffer%obj)
457 96 : END FUNCTION fb_buffer_d_has_data
458 :
459 : ! **************************************************************************************************
460 : !> \brief creates a fb_buffer object
461 : !> \param buffer : fb_buffer object
462 : !> \param max_size : requested total size of the data array
463 : !> \param nslices : total number of slices for the data
464 : !> \param data_1d : the data to be copied to the buffer
465 : !> \param sizes : the size of the slices in the buffer
466 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
467 : ! **************************************************************************************************
468 48 : SUBROUTINE fb_buffer_d_create(buffer, &
469 : max_size, &
470 : nslices, &
471 48 : data_1d, &
472 48 : sizes)
473 : TYPE(fb_buffer_d_obj), INTENT(INOUT) :: buffer
474 : INTEGER, INTENT(IN), OPTIONAL :: max_size, nslices
475 : REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL :: data_1d
476 : INTEGER, DIMENSION(:), INTENT(IN), OPTIONAL :: sizes
477 :
478 : INTEGER :: my_max_size, my_ndata, my_nslices
479 : LOGICAL :: check_ok
480 :
481 : ! check optional input
482 :
483 48 : IF (PRESENT(data_1d)) THEN
484 0 : CPASSERT(PRESENT(sizes))
485 : END IF
486 :
487 48 : CPASSERT(.NOT. ASSOCIATED(buffer%obj))
488 48 : ALLOCATE (buffer%obj)
489 : ! work out the size of the data array and number of slices
490 48 : my_max_size = 0
491 48 : my_nslices = 0
492 48 : my_ndata = 0
493 : NULLIFY (buffer%obj%data_1d, &
494 : buffer%obj%disps)
495 : ! work out sizes
496 48 : IF (PRESENT(max_size)) my_max_size = max_size
497 48 : IF (PRESENT(nslices)) my_nslices = nslices
498 48 : IF (PRESENT(sizes)) THEN
499 0 : my_nslices = MIN(my_nslices, SIZE(sizes))
500 0 : my_ndata = SUM(sizes(1:my_nslices))
501 0 : my_max_size = MAX(my_max_size, my_ndata)
502 : END IF
503 : ! allocate the arrays
504 96 : ALLOCATE (buffer%obj%data_1d(my_max_size))
505 144 : ALLOCATE (buffer%obj%disps(my_nslices + 1))
506 48 : buffer%obj%data_1d = 0
507 96 : buffer%obj%disps = 0
508 : ! set n for buffer before calc disps
509 48 : buffer%obj%n = my_nslices
510 : ! compute disps from sizes if required
511 48 : IF (PRESENT(sizes)) THEN
512 0 : CALL fb_buffer_calc_disps(buffer, sizes)
513 : END IF
514 : ! copy data
515 48 : IF (PRESENT(data_1d)) THEN
516 : check_ok = SIZE(data_1d) >= my_max_size .AND. &
517 0 : PRESENT(sizes)
518 0 : CPASSERT(check_ok)
519 0 : buffer%obj%data_1d(1:my_ndata) = data_1d(1:my_ndata)
520 : END IF
521 48 : END SUBROUTINE fb_buffer_d_create
522 :
523 : ! **************************************************************************************************
524 : !> \brief add some data into the buffer
525 : !> \param buffer : fb_buffer object
526 : !> \param data_1d : data to be copied into the object
527 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
528 : ! **************************************************************************************************
529 1664 : SUBROUTINE fb_buffer_d_add(buffer, data_1d)
530 : TYPE(fb_buffer_d_obj), INTENT(INOUT) :: buffer
531 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: data_1d
532 :
533 : INTEGER :: new_data_size, new_n, this_size
534 1664 : INTEGER, DIMENSION(:), POINTER :: new_disps
535 1664 : REAL(KIND=dp), DIMENSION(:), POINTER :: new_data
536 :
537 1664 : NULLIFY (new_disps, new_data)
538 :
539 1664 : this_size = SIZE(data_1d)
540 1664 : new_n = buffer%obj%n + 1
541 1664 : new_data_size = buffer%obj%disps(new_n) + this_size
542 : ! resize when needed
543 1664 : IF (SIZE(buffer%obj%disps) < new_n + 1) THEN
544 864 : ALLOCATE (new_disps(new_n*2))
545 6336 : new_disps = 0
546 3312 : new_disps(1:buffer%obj%n + 1) = buffer%obj%disps(1:buffer%obj%n + 1)
547 288 : DEALLOCATE (buffer%obj%disps)
548 288 : buffer%obj%disps => new_disps
549 : END IF
550 1664 : IF (SIZE(buffer%obj%data_1d) < new_data_size) THEN
551 720 : ALLOCATE (new_data(new_data_size*2))
552 711600 : new_data = 0.0_dp
553 : new_data(1:buffer%obj%disps(new_n)) = &
554 324720 : buffer%obj%data_1d(1:buffer%obj%disps(new_n))
555 240 : DEALLOCATE (buffer%obj%data_1d)
556 240 : buffer%obj%data_1d => new_data
557 : END IF
558 : ! append to the buffer
559 1664 : buffer%obj%disps(new_n + 1) = new_data_size
560 : buffer%obj%data_1d(buffer%obj%disps(new_n) + 1:new_data_size) = &
561 222976 : data_1d(1:this_size)
562 1664 : buffer%obj%n = new_n
563 1664 : END SUBROUTINE fb_buffer_d_add
564 :
565 : ! **************************************************************************************************
566 : !> \brief compute the displacements of each slice in a data buffer from
567 : !> a given list of sizes of each slice
568 : !> \param buffer : fb_buffer object
569 : !> \param sizes : list of sizes of each slice on input
570 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
571 : ! **************************************************************************************************
572 0 : SUBROUTINE fb_buffer_d_calc_disps(buffer, sizes)
573 : TYPE(fb_buffer_d_obj), INTENT(INOUT) :: buffer
574 : INTEGER, DIMENSION(:), INTENT(IN) :: sizes
575 :
576 : INTEGER :: ii
577 :
578 0 : CPASSERT(SIZE(sizes) >= buffer%obj%n)
579 0 : buffer%obj%disps(1) = 0
580 0 : DO ii = 2, buffer%obj%n + 1
581 0 : buffer%obj%disps(ii) = buffer%obj%disps(ii - 1) + sizes(ii - 1)
582 : END DO
583 0 : END SUBROUTINE fb_buffer_d_calc_disps
584 :
585 : ! **************************************************************************************************
586 : !> \brief compute the sizes of each slice
587 : !> \param buffer : fb_buffer object
588 : !> \param sizes : list of sizes of each slice on output
589 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
590 : ! **************************************************************************************************
591 0 : SUBROUTINE fb_buffer_d_calc_sizes(buffer, sizes)
592 : TYPE(fb_buffer_d_obj), INTENT(IN) :: buffer
593 : INTEGER, DIMENSION(:), INTENT(OUT) :: sizes
594 :
595 : INTEGER :: ii
596 :
597 0 : CPASSERT(SIZE(sizes) >= buffer%obj%n)
598 0 : DO ii = 1, buffer%obj%n
599 0 : sizes(ii) = buffer%obj%disps(ii + 1) - buffer%obj%disps(ii)
600 : END DO
601 0 : END SUBROUTINE fb_buffer_d_calc_sizes
602 :
603 : ! **************************************************************************************************
604 : !> \brief get data from the fb_buffer object
605 : !> \param buffer : fb_buffer object
606 : !> \param i_slice : see data_1d, data_2d
607 : !> \param n : outputs number of slices in data array
608 : !> \param data_size : outputs the total size of stored data
609 : !> \param sizes : outputs sizes of the slices in data array
610 : !> \param disps : outputs displacements in the data array for each slice
611 : !> \param data_1d : if i_slice is present:
612 : !> returns pointer to the section of data array corresponding
613 : !> to i_slice-th slice
614 : !> else:
615 : !> return pointer to the entire non-empty part of the data array
616 : !> \param data_2d : similar to data_1d, but with the 1D data array reshaped to 2D
617 : !> works only with i_slice present
618 : !> \param data_2d_ld : leading dimension for data_2d for slice i_slice
619 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
620 : ! **************************************************************************************************
621 5120 : SUBROUTINE fb_buffer_d_get(buffer, &
622 : i_slice, &
623 : n, &
624 : data_size, &
625 5120 : sizes, &
626 5120 : disps, &
627 : data_1d, &
628 : data_2d, &
629 : data_2d_ld)
630 : TYPE(fb_buffer_d_obj), INTENT(IN) :: buffer
631 : INTEGER, INTENT(IN), OPTIONAL :: i_slice
632 : INTEGER, INTENT(OUT), OPTIONAL :: n, data_size
633 : INTEGER, DIMENSION(:), INTENT(OUT), OPTIONAL :: sizes, disps
634 : REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER :: data_1d
635 : REAL(KIND=dp), DIMENSION(:, :), OPTIONAL, POINTER :: data_2d
636 : INTEGER, INTENT(IN), OPTIONAL :: data_2d_ld
637 :
638 : INTEGER :: ncols, slice_size
639 :
640 5120 : IF (PRESENT(n)) n = buffer%obj%n
641 5120 : IF (PRESENT(data_size)) data_size = buffer%obj%disps(buffer%obj%n + 1)
642 5120 : IF (PRESENT(sizes)) THEN
643 0 : CALL fb_buffer_calc_sizes(buffer, sizes)
644 : END IF
645 5120 : IF (PRESENT(disps)) THEN
646 0 : CPASSERT(SIZE(disps) >= buffer%obj%n)
647 0 : disps(1:buffer%obj%n) = buffer%obj%disps(1:buffer%obj%n)
648 : END IF
649 5120 : IF (PRESENT(data_1d)) THEN
650 0 : IF (PRESENT(i_slice)) THEN
651 0 : CPASSERT(i_slice <= buffer%obj%n)
652 : data_1d => buffer%obj%data_1d(buffer%obj%disps(i_slice) + 1: &
653 0 : buffer%obj%disps(i_slice + 1))
654 : ELSE
655 0 : data_1d => buffer%obj%data_1d(1:buffer%obj%disps(buffer%obj%n + 1))
656 : END IF
657 : END IF
658 5120 : IF (PRESENT(data_2d)) THEN
659 5120 : CPASSERT(PRESENT(data_2d_ld))
660 5120 : CPASSERT(PRESENT(i_slice))
661 : ! cannot, or rather, it is inefficient to use reshape here, as
662 : ! a) reshape does not return a targeted array, so cannot
663 : ! associate pointer unless copied to a targeted array. b) in
664 : ! F2003 standard, pointers should rank remap automatically by
665 : ! association to a rank 1 array
666 5120 : slice_size = buffer%obj%disps(i_slice + 1) - buffer%obj%disps(i_slice)
667 5120 : ncols = slice_size/data_2d_ld
668 5120 : CPASSERT(slice_size == data_2d_ld*ncols)
669 : data_2d(1:data_2d_ld, 1:ncols) => &
670 : buffer%obj%data_1d(buffer%obj%disps(i_slice) + 1: &
671 5120 : buffer%obj%disps(i_slice + 1))
672 : END IF
673 5120 : END SUBROUTINE fb_buffer_d_get
674 :
675 : ! **************************************************************************************************
676 : !> \brief replace a slice of the buffer, the replace data size must be
677 : !> identical to the original slice size
678 : !> \param buffer : fb_buffer object
679 : !> \param i_slice : the slice index in the buffer
680 : !> \param data_1d : the data to replace the slice
681 : !> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
682 : ! **************************************************************************************************
683 0 : SUBROUTINE fb_buffer_d_replace(buffer, i_slice, data_1d)
684 : TYPE(fb_buffer_d_obj), INTENT(INOUT) :: buffer
685 : INTEGER, INTENT(IN) :: i_slice
686 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: data_1d
687 :
688 : INTEGER :: slice_size
689 :
690 0 : slice_size = buffer%obj%disps(i_slice + 1) - buffer%obj%disps(i_slice)
691 0 : CPASSERT(SIZE(data_1d) == slice_size)
692 : buffer%obj%data_1d(buffer%obj%disps(i_slice) + 1: &
693 0 : buffer%obj%disps(i_slice + 1)) = data_1d
694 0 : END SUBROUTINE fb_buffer_d_replace
695 :
696 0 : END MODULE qs_fb_buffer_types
|