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