(git:374b731)
Loading...
Searching...
No Matches
dbt_split.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 Routines to split blocks and to convert between tensors with different block sizes.
10!> \author Patrick Seewald
11! **************************************************************************************************
13
14
15
18 USE dbt_block, ONLY: dbt_iterator_type, &
29 USE dbt_types, ONLY: dbt_create, &
30 dbt_type, &
36 dbt_clear, &
43 dbt_filter, &
45 USE kinds, ONLY: dp, dp
46
47#include "../base/base_uses.f90"
48 IMPLICIT NONE
49 PRIVATE
50 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dbt_split'
51 PUBLIC :: &
57
58CONTAINS
59
60! **************************************************************************************************
61!> \brief Split tensor blocks into smaller blocks
62!> \param tensor_in Input tensor
63!> \param tensor_out Output tensor (splitted blocks)
64!> \param blk_size_i block sizes for each of the tensor dimensions
65!> \param nodata don't copy data from tensor_in to tensor_out
66!> \author Patrick Seewald
67! **************************************************************************************************
68 SUBROUTINE dbt_split_blocks_generic(tensor_in, tensor_out, blk_size_1, blk_size_2, blk_size_3, blk_size_4, nodata)
69 TYPE(dbt_type), INTENT(INOUT) :: tensor_in
70 TYPE(dbt_type), INTENT(OUT) :: tensor_out
71 INTEGER, DIMENSION(:), INTENT(IN), OPTIONAL :: blk_size_1, blk_size_2, blk_size_3, blk_size_4
72 LOGICAL, INTENT(IN), OPTIONAL :: nodata
73
74 TYPE(dbt_distribution_type) :: dist_old, dist_split
75 TYPE(dbt_iterator_type) :: iter
76 INTEGER, DIMENSION(:), ALLOCATABLE :: nd_dist_split_1, nd_dist_split_2, nd_dist_split_3, nd_dist_split_4
77 INTEGER, DIMENSION(:), ALLOCATABLE :: nd_blk_size_split_1, nd_blk_size_split_2, nd_blk_size_split_3,&
78 & nd_blk_size_split_4
79 INTEGER, DIMENSION(:), ALLOCATABLE :: index_split_offset_1, index_split_offset_2, index_split_offset_3,&
80 & index_split_offset_4
81 INTEGER, DIMENSION(:), ALLOCATABLE :: inblock_offset_1, inblock_offset_2, inblock_offset_3, inblock_offset_4
82 INTEGER, DIMENSION(:), ALLOCATABLE :: blk_nsplit_1, blk_nsplit_2, blk_nsplit_3, blk_nsplit_4
83 INTEGER :: split_blk_1, split_blk_2, split_blk_3, split_blk_4
84 INTEGER :: idim, i, isplit_sum, nsplit, handle, splitsum, bcount
85 INTEGER, DIMENSION(:, :), ALLOCATABLE :: blks_to_allocate
86 INTEGER, DIMENSION(:), ALLOCATABLE :: dist_d, blk_size_d, blk_size_split_d, dist_split_d
87 INTEGER, DIMENSION(ndims_matrix_row(tensor_in)) :: map1_2d
88 INTEGER, DIMENSION(ndims_matrix_column(tensor_in)) :: map2_2d
89 INTEGER, DIMENSION(ndims_tensor(tensor_in)) :: blk_index, blk_size, blk_offset, &
90 blk_shape
91 INTEGER, DIMENSION(4) :: bi_split, inblock_offset
92 LOGICAL :: found
93
94 REAL(dp), DIMENSION(:,:), ALLOCATABLE :: block_2d
95 REAL(dp), DIMENSION(:,:,:), ALLOCATABLE :: block_3d
96 REAL(dp), DIMENSION(:,:,:,:), ALLOCATABLE :: block_4d
97 CHARACTER(LEN=*), PARAMETER :: routinen = 'dbt_split_blocks_generic'
98
99 CALL timeset(routinen, handle)
100
101 dist_old = dbt_distribution(tensor_in)
102
103 DO idim = 1, ndims_tensor(tensor_in)
104 CALL get_ith_array(dist_old%nd_dist, idim, dist_d)
105 CALL get_ith_array(tensor_in%blk_sizes, idim, blk_size_d)
106
107 IF (idim == 1) THEN
108 ! split block index offset for each normal block index
109 ALLOCATE (index_split_offset_1(SIZE(dist_d)))
110 ! how many split blocks for each normal block index
111 ALLOCATE (blk_nsplit_1(SIZE(dist_d)))
112 ! data offset of split blocks w.r.t. corresponding normal block
113 ALLOCATE (inblock_offset_1(SIZE(blk_size_1)))
114 ALLOCATE (blk_size_split_d, source=blk_size_1)
115 END IF
116 IF (idim == 2) THEN
117 ! split block index offset for each normal block index
118 ALLOCATE (index_split_offset_2(SIZE(dist_d)))
119 ! how many split blocks for each normal block index
120 ALLOCATE (blk_nsplit_2(SIZE(dist_d)))
121 ! data offset of split blocks w.r.t. corresponding normal block
122 ALLOCATE (inblock_offset_2(SIZE(blk_size_2)))
123 ALLOCATE (blk_size_split_d, source=blk_size_2)
124 END IF
125 IF (idim == 3) THEN
126 ! split block index offset for each normal block index
127 ALLOCATE (index_split_offset_3(SIZE(dist_d)))
128 ! how many split blocks for each normal block index
129 ALLOCATE (blk_nsplit_3(SIZE(dist_d)))
130 ! data offset of split blocks w.r.t. corresponding normal block
131 ALLOCATE (inblock_offset_3(SIZE(blk_size_3)))
132 ALLOCATE (blk_size_split_d, source=blk_size_3)
133 END IF
134 IF (idim == 4) THEN
135 ! split block index offset for each normal block index
136 ALLOCATE (index_split_offset_4(SIZE(dist_d)))
137 ! how many split blocks for each normal block index
138 ALLOCATE (blk_nsplit_4(SIZE(dist_d)))
139 ! data offset of split blocks w.r.t. corresponding normal block
140 ALLOCATE (inblock_offset_4(SIZE(blk_size_4)))
141 ALLOCATE (blk_size_split_d, source=blk_size_4)
142 END IF
143
144 ! distribution vector for split blocks
145 ALLOCATE (dist_split_d(SIZE(blk_size_split_d)))
146
147 isplit_sum = 0 ! counting splits
148 DO i = 1, SIZE(blk_size_d)
149 nsplit = 0 ! number of splits for current normal block
150 splitsum = 0 ! summing split block sizes for current normal block
151 DO WHILE (splitsum < blk_size_d(i))
152 nsplit = nsplit + 1
153 isplit_sum = isplit_sum + 1
154 IF (idim == 1) inblock_offset_1(isplit_sum) = splitsum
155 IF (idim == 2) inblock_offset_2(isplit_sum) = splitsum
156 IF (idim == 3) inblock_offset_3(isplit_sum) = splitsum
157 IF (idim == 4) inblock_offset_4(isplit_sum) = splitsum
158 dist_split_d(isplit_sum) = dist_d(i)
159 splitsum = splitsum + blk_size_split_d(isplit_sum)
160 END DO
161 cpassert(splitsum == blk_size_d(i))
162 IF (idim == 1) THEN
163 blk_nsplit_1(i) = nsplit
164 index_split_offset_1(i) = isplit_sum - nsplit
165 END IF
166 IF (idim == 2) THEN
167 blk_nsplit_2(i) = nsplit
168 index_split_offset_2(i) = isplit_sum - nsplit
169 END IF
170 IF (idim == 3) THEN
171 blk_nsplit_3(i) = nsplit
172 index_split_offset_3(i) = isplit_sum - nsplit
173 END IF
174 IF (idim == 4) THEN
175 blk_nsplit_4(i) = nsplit
176 index_split_offset_4(i) = isplit_sum - nsplit
177 END IF
178 END DO
179
180 IF (idim == 1) THEN
181 ALLOCATE (nd_dist_split_1, source=dist_split_d)
182 ALLOCATE (nd_blk_size_split_1, source=blk_size_split_d)
183 END IF
184 IF (idim == 2) THEN
185 ALLOCATE (nd_dist_split_2, source=dist_split_d)
186 ALLOCATE (nd_blk_size_split_2, source=blk_size_split_d)
187 END IF
188 IF (idim == 3) THEN
189 ALLOCATE (nd_dist_split_3, source=dist_split_d)
190 ALLOCATE (nd_blk_size_split_3, source=blk_size_split_d)
191 END IF
192 IF (idim == 4) THEN
193 ALLOCATE (nd_dist_split_4, source=dist_split_d)
194 ALLOCATE (nd_blk_size_split_4, source=blk_size_split_d)
195 END IF
196 DEALLOCATE (dist_split_d)
197 DEALLOCATE (blk_size_split_d)
198
199 END DO
200
201 CALL dbt_get_mapping_info(tensor_in%nd_index_blk, map1_2d=map1_2d, map2_2d=map2_2d)
202
203 IF (ndims_tensor(tensor_in) == 2) THEN
204 CALL dbt_distribution_new_expert(dist_split, tensor_in%pgrid, map1_2d, map2_2d, &
205 nd_dist_split_1, nd_dist_split_2)
206 CALL dbt_create(tensor_out, tensor_in%name, dist_split, map1_2d, map2_2d, &
207 nd_blk_size_split_1, nd_blk_size_split_2)
208 END IF
209 IF (ndims_tensor(tensor_in) == 3) THEN
210 CALL dbt_distribution_new_expert(dist_split, tensor_in%pgrid, map1_2d, map2_2d, &
211 nd_dist_split_1, nd_dist_split_2, nd_dist_split_3)
212 CALL dbt_create(tensor_out, tensor_in%name, dist_split, map1_2d, map2_2d, &
213 nd_blk_size_split_1, nd_blk_size_split_2, nd_blk_size_split_3)
214 END IF
215 IF (ndims_tensor(tensor_in) == 4) THEN
216 CALL dbt_distribution_new_expert(dist_split, tensor_in%pgrid, map1_2d, map2_2d, &
217 nd_dist_split_1, nd_dist_split_2, nd_dist_split_3, nd_dist_split_4)
218 CALL dbt_create(tensor_out, tensor_in%name, dist_split, map1_2d, map2_2d, &
219 nd_blk_size_split_1, nd_blk_size_split_2, nd_blk_size_split_3, nd_blk_size_split_4)
220 END IF
221
222 CALL dbt_distribution_destroy(dist_split)
223
224 IF (PRESENT(nodata)) THEN
225 IF (nodata) THEN
226 CALL timestop(handle)
227 RETURN
228 END IF
229 END IF
230
231!$OMP PARALLEL DEFAULT(NONE) &
232!$OMP SHARED(tensor_in,tensor_out) &
233!$OMP SHARED(blk_nsplit_1, blk_nsplit_2, blk_nsplit_3, blk_nsplit_4) &
234!$OMP SHARED(inblock_offset_1, inblock_offset_2, inblock_offset_3, inblock_offset_4) &
235!$OMP SHARED(blk_size_1, blk_size_2, blk_size_3, blk_size_4) &
236!$OMP SHARED(index_split_offset_1, index_split_offset_2, index_split_offset_3, index_split_offset_4) &
237!$OMP PRIVATE(iter,found,bcount,blks_to_allocate,bi_split,inblock_offset) &
238!$OMP PRIVATE(blk_index,blk_size,blk_offset,blk_shape) &
239!$OMP PRIVATE(block_2d,block_3d,block_4d)
240 CALL dbt_iterator_start(iter, tensor_in)
241
242 bcount = 0
243 DO WHILE (dbt_iterator_blocks_left(iter))
244 CALL dbt_iterator_next_block(iter, blk_index, blk_size=blk_size)
245 IF (ndims_tensor(tensor_in) == 2) THEN
246 DO split_blk_1 = 1, blk_nsplit_1(blk_index(1))
247 DO split_blk_2 = 1, blk_nsplit_2(blk_index(2))
248 bcount = bcount + 1
249 END DO
250 END DO
251 END IF
252 IF (ndims_tensor(tensor_in) == 3) THEN
253 DO split_blk_1 = 1, blk_nsplit_1(blk_index(1))
254 DO split_blk_2 = 1, blk_nsplit_2(blk_index(2))
255 DO split_blk_3 = 1, blk_nsplit_3(blk_index(3))
256 bcount = bcount + 1
257 END DO
258 END DO
259 END DO
260 END IF
261 IF (ndims_tensor(tensor_in) == 4) THEN
262 DO split_blk_1 = 1, blk_nsplit_1(blk_index(1))
263 DO split_blk_2 = 1, blk_nsplit_2(blk_index(2))
264 DO split_blk_3 = 1, blk_nsplit_3(blk_index(3))
265 DO split_blk_4 = 1, blk_nsplit_4(blk_index(4))
266 bcount = bcount + 1
267 END DO
268 END DO
269 END DO
270 END DO
271 END IF
272 END DO
273 CALL dbt_iterator_stop(iter)
274
275 ALLOCATE (blks_to_allocate(bcount, ndims_tensor(tensor_in)))
276
277 CALL dbt_iterator_start(iter, tensor_in)
278
279 bcount = 0
280 DO WHILE (dbt_iterator_blocks_left(iter))
281 CALL dbt_iterator_next_block(iter, blk_index, blk_size=blk_size, blk_offset=blk_offset)
282
283 IF (ndims_tensor(tensor_in) == 2) THEN
284 DO split_blk_1 = 1, blk_nsplit_1(blk_index(1))
285 bi_split(1) = index_split_offset_1(blk_index(1)) + split_blk_1
286 DO split_blk_2 = 1, blk_nsplit_2(blk_index(2))
287 bi_split(2) = index_split_offset_2(blk_index(2)) + split_blk_2
288 bcount = bcount + 1
289 blks_to_allocate(bcount, :) = bi_split(1:ndims_tensor(tensor_in))
290 END DO
291 END DO
292 END IF
293 IF (ndims_tensor(tensor_in) == 3) THEN
294 DO split_blk_1 = 1, blk_nsplit_1(blk_index(1))
295 bi_split(1) = index_split_offset_1(blk_index(1)) + split_blk_1
296 DO split_blk_2 = 1, blk_nsplit_2(blk_index(2))
297 bi_split(2) = index_split_offset_2(blk_index(2)) + split_blk_2
298 DO split_blk_3 = 1, blk_nsplit_3(blk_index(3))
299 bi_split(3) = index_split_offset_3(blk_index(3)) + split_blk_3
300 bcount = bcount + 1
301 blks_to_allocate(bcount, :) = bi_split(1:ndims_tensor(tensor_in))
302 END DO
303 END DO
304 END DO
305 END IF
306 IF (ndims_tensor(tensor_in) == 4) THEN
307 DO split_blk_1 = 1, blk_nsplit_1(blk_index(1))
308 bi_split(1) = index_split_offset_1(blk_index(1)) + split_blk_1
309 DO split_blk_2 = 1, blk_nsplit_2(blk_index(2))
310 bi_split(2) = index_split_offset_2(blk_index(2)) + split_blk_2
311 DO split_blk_3 = 1, blk_nsplit_3(blk_index(3))
312 bi_split(3) = index_split_offset_3(blk_index(3)) + split_blk_3
313 DO split_blk_4 = 1, blk_nsplit_4(blk_index(4))
314 bi_split(4) = index_split_offset_4(blk_index(4)) + split_blk_4
315 bcount = bcount + 1
316 blks_to_allocate(bcount, :) = bi_split(1:ndims_tensor(tensor_in))
317 END DO
318 END DO
319 END DO
320 END DO
321 END IF
322 END DO
323
324 CALL dbt_iterator_stop(iter)
325
326 CALL dbt_reserve_blocks(tensor_out, blks_to_allocate)
327
328 CALL dbt_iterator_start(iter, tensor_in)
329
330 DO WHILE (dbt_iterator_blocks_left(iter))
331 CALL dbt_iterator_next_block(iter, blk_index, blk_size=blk_size, blk_offset=blk_offset)
332 IF (ndims_tensor(tensor_in) == 2) THEN
333 CALL dbt_get_block(tensor_in, blk_index, block_2d, found)
334 cpassert(found)
335 END IF
336 IF (ndims_tensor(tensor_in) == 3) THEN
337 CALL dbt_get_block(tensor_in, blk_index, block_3d, found)
338 cpassert(found)
339 END IF
340 IF (ndims_tensor(tensor_in) == 4) THEN
341 CALL dbt_get_block(tensor_in, blk_index, block_4d, found)
342 cpassert(found)
343 END IF
344 IF (ndims_tensor(tensor_in) == 2) THEN
345 DO split_blk_1 = 1, blk_nsplit_1(blk_index(1))
346 ! split block index
347 bi_split(1) = index_split_offset_1(blk_index(1)) + split_blk_1
348 blk_shape(1) = blk_size_1(bi_split(1))
349 DO split_blk_2 = 1, blk_nsplit_2(blk_index(2))
350 ! split block index
351 bi_split(2) = index_split_offset_2(blk_index(2)) + split_blk_2
352 blk_shape(2) = blk_size_2(bi_split(2))
353
354 inblock_offset(1) = inblock_offset_1(bi_split(1))
355 inblock_offset(2) = inblock_offset_2(bi_split(2))
356 CALL dbt_put_block(tensor_out, bi_split(1:2), &
357 blk_shape, &
358 block_2d( &
359 inblock_offset(1) + 1:inblock_offset(1) + blk_shape(1), inblock_offset(2) +&
360 & 1:inblock_offset(2) + blk_shape(2)))
361
362 END DO
363 END DO
364
365 DEALLOCATE (block_2d)
366 END IF
367 IF (ndims_tensor(tensor_in) == 3) THEN
368 DO split_blk_1 = 1, blk_nsplit_1(blk_index(1))
369 ! split block index
370 bi_split(1) = index_split_offset_1(blk_index(1)) + split_blk_1
371 blk_shape(1) = blk_size_1(bi_split(1))
372 DO split_blk_2 = 1, blk_nsplit_2(blk_index(2))
373 ! split block index
374 bi_split(2) = index_split_offset_2(blk_index(2)) + split_blk_2
375 blk_shape(2) = blk_size_2(bi_split(2))
376 DO split_blk_3 = 1, blk_nsplit_3(blk_index(3))
377 ! split block index
378 bi_split(3) = index_split_offset_3(blk_index(3)) + split_blk_3
379 blk_shape(3) = blk_size_3(bi_split(3))
380
381 inblock_offset(1) = inblock_offset_1(bi_split(1))
382 inblock_offset(2) = inblock_offset_2(bi_split(2))
383 inblock_offset(3) = inblock_offset_3(bi_split(3))
384 CALL dbt_put_block(tensor_out, bi_split(1:3), &
385 blk_shape, &
386 block_3d( &
387 inblock_offset(1) + 1:inblock_offset(1) + blk_shape(1), inblock_offset(2) +&
388 & 1:inblock_offset(2) + blk_shape(2), inblock_offset(3) + 1:inblock_offset(3) +&
389 & blk_shape(3)))
390
391 END DO
392 END DO
393 END DO
394
395 DEALLOCATE (block_3d)
396 END IF
397 IF (ndims_tensor(tensor_in) == 4) THEN
398 DO split_blk_1 = 1, blk_nsplit_1(blk_index(1))
399 ! split block index
400 bi_split(1) = index_split_offset_1(blk_index(1)) + split_blk_1
401 blk_shape(1) = blk_size_1(bi_split(1))
402 DO split_blk_2 = 1, blk_nsplit_2(blk_index(2))
403 ! split block index
404 bi_split(2) = index_split_offset_2(blk_index(2)) + split_blk_2
405 blk_shape(2) = blk_size_2(bi_split(2))
406 DO split_blk_3 = 1, blk_nsplit_3(blk_index(3))
407 ! split block index
408 bi_split(3) = index_split_offset_3(blk_index(3)) + split_blk_3
409 blk_shape(3) = blk_size_3(bi_split(3))
410 DO split_blk_4 = 1, blk_nsplit_4(blk_index(4))
411 ! split block index
412 bi_split(4) = index_split_offset_4(blk_index(4)) + split_blk_4
413 blk_shape(4) = blk_size_4(bi_split(4))
414
415 inblock_offset(1) = inblock_offset_1(bi_split(1))
416 inblock_offset(2) = inblock_offset_2(bi_split(2))
417 inblock_offset(3) = inblock_offset_3(bi_split(3))
418 inblock_offset(4) = inblock_offset_4(bi_split(4))
419 CALL dbt_put_block(tensor_out, bi_split(1:4), &
420 blk_shape, &
421 block_4d( &
422 inblock_offset(1) + 1:inblock_offset(1) + blk_shape(1), inblock_offset(2) +&
423 & 1:inblock_offset(2) + blk_shape(2), inblock_offset(3) + 1:inblock_offset(3) +&
424 & blk_shape(3), inblock_offset(4) + 1:inblock_offset(4) + blk_shape(4)))
425
426 END DO
427 END DO
428 END DO
429 END DO
430
431 DEALLOCATE (block_4d)
432 END IF
433 END DO
434 CALL dbt_iterator_stop(iter)
435!$OMP END PARALLEL
436
437 CALL dbt_finalize(tensor_out)
438
439 ! remove blocks that are exactly 0, these can occur if a cropping operation was performed before splitting
440 CALL dbt_filter(tensor_out, tiny(0.0_dp))
441
442 CALL timestop(handle)
443
444 END SUBROUTINE
445
446! **************************************************************************************************
447!> \brief Split tensor blocks into smaller blocks of maximum size PRODUCT(block_sizes).
448!> \param tensor_in Input tensor
449!> \param tensor_out Output tensor (split blocks)
450!> \param block_sizes block sizes for each of the tensor dimensions
451!> \param nodata don't copy data from tensor_in to tensor_out
452!> \author Patrick Seewald
453! **************************************************************************************************
454 SUBROUTINE dbt_split_blocks(tensor_in, tensor_out, block_sizes, nodata)
455
456 TYPE(dbt_type), INTENT(INOUT) :: tensor_in
457 TYPE(dbt_type), INTENT(OUT) :: tensor_out
458 INTEGER, DIMENSION(ndims_tensor(tensor_in)), &
459 INTENT(IN) :: block_sizes
460 LOGICAL, INTENT(IN), OPTIONAL :: nodata
461
462 INTEGER, DIMENSION(:), ALLOCATABLE :: nd_blk_size_split_1, nd_blk_size_split_2,&
463 & nd_blk_size_split_3, nd_blk_size_split_4
464 INTEGER :: idim, i, isplit_sum, blk_remainder, nsplit, isplit
465 INTEGER, DIMENSION(:), ALLOCATABLE :: blk_size_d, blk_size_split_d
466
467 DO idim = 1, ndims_tensor(tensor_in)
468 CALL get_ith_array(tensor_in%blk_sizes, idim, blk_size_d)
469
470 isplit_sum = 0
471 DO i = 1, SIZE(blk_size_d)
472 nsplit = (blk_size_d(i) + block_sizes(idim) - 1)/block_sizes(idim)
473 isplit_sum = isplit_sum + nsplit
474 END DO
475
476 ALLOCATE (blk_size_split_d(isplit_sum))
477
478 isplit_sum = 0
479 DO i = 1, SIZE(blk_size_d)
480 nsplit = (blk_size_d(i) + block_sizes(idim) - 1)/block_sizes(idim)
481 blk_remainder = blk_size_d(i)
482 DO isplit = 1, nsplit
483 isplit_sum = isplit_sum + 1
484 blk_size_split_d(isplit_sum) = min(block_sizes(idim), blk_remainder)
485 blk_remainder = blk_remainder - block_sizes(idim)
486 END DO
487
488 END DO
489
490 IF (idim == 1) THEN
491 ALLOCATE (nd_blk_size_split_1, source=blk_size_split_d)
492 END IF
493 IF (idim == 2) THEN
494 ALLOCATE (nd_blk_size_split_2, source=blk_size_split_d)
495 END IF
496 IF (idim == 3) THEN
497 ALLOCATE (nd_blk_size_split_3, source=blk_size_split_d)
498 END IF
499 IF (idim == 4) THEN
500 ALLOCATE (nd_blk_size_split_4, source=blk_size_split_d)
501 END IF
502 DEALLOCATE (blk_size_split_d)
503 END DO
504
505 IF (ndims_tensor(tensor_in) == 2) CALL dbt_split_blocks_generic(tensor_in, tensor_out, &
506 nd_blk_size_split_1, nd_blk_size_split_2, &
507 nodata=nodata)
508 IF (ndims_tensor(tensor_in) == 3) CALL dbt_split_blocks_generic(tensor_in, tensor_out, &
509 nd_blk_size_split_1, nd_blk_size_split_2,&
510 & nd_blk_size_split_3, &
511 nodata=nodata)
512 IF (ndims_tensor(tensor_in) == 4) CALL dbt_split_blocks_generic(tensor_in, tensor_out, &
513 nd_blk_size_split_1, nd_blk_size_split_2,&
514 & nd_blk_size_split_3, nd_blk_size_split_&
515 &4, &
516 nodata=nodata)
517
518 END SUBROUTINE
519
520! **************************************************************************************************
521!> \brief Copy tensor with split blocks to tensor with original block sizes.
522!> \param tensor_split_in tensor with smaller blocks
523!> \param tensor_out original tensor
524!> \author Patrick Seewald
525! **************************************************************************************************
526 SUBROUTINE dbt_split_copyback(tensor_split_in, tensor_out, summation)
527 TYPE(dbt_type), INTENT(INOUT) :: tensor_split_in
528 TYPE(dbt_type), INTENT(INOUT) :: tensor_out
529 LOGICAL, INTENT(IN), OPTIONAL :: summation
530 INTEGER, DIMENSION(:), ALLOCATABLE :: first_split_d, last_split_d
531 INTEGER, DIMENSION(:), ALLOCATABLE :: blk_size_split_d, blk_size_d
532 INTEGER, DIMENSION(:), ALLOCATABLE :: last_split_1, last_split_2, last_split_3, last_split_4, &
533 first_split_1, first_split_2, first_split_3,&
534 & first_split_4, &
535 split_1, split_2, split_3, split_4
536 INTEGER, DIMENSION(:), ALLOCATABLE :: inblock_offset_1, inblock_offset_2, inblock_offset_3,&
537 & inblock_offset_4, blk_size_split_1, blk_size_split_2, blk_size_split_3, blk_size_split_4
538 INTEGER, DIMENSION(:, :), ALLOCATABLE :: blks_to_allocate
539 INTEGER :: idim, iblk, bcount
540 INTEGER :: iblk_1, iblk_2, iblk_3, iblk_4, isplit_sum, splitsum
541 TYPE(dbt_iterator_type) :: iter
542 INTEGER, DIMENSION(ndims_tensor(tensor_out)) :: blk_index, blk_size, blk_offset, blk_shape, blk_index_n
543 LOGICAL :: found
544
545 INTEGER, DIMENSION(4) :: inblock_offset
546 INTEGER :: handle
547 CHARACTER(LEN=*), PARAMETER :: routinen = 'dbt_split_copyback'
548 REAL(dp), DIMENSION(:,:), ALLOCATABLE :: block_2d
549 REAL(dp), DIMENSION(:,:), ALLOCATABLE :: block_split_2d
550 REAL(dp), DIMENSION(:,:,:), ALLOCATABLE :: block_3d
551 REAL(dp), DIMENSION(:,:,:), ALLOCATABLE :: block_split_3d
552 REAL(dp), DIMENSION(:,:,:,:), ALLOCATABLE :: block_4d
553 REAL(dp), DIMENSION(:,:,:,:), ALLOCATABLE :: block_split_4d
554
555 CALL timeset(routinen, handle)
556 cpassert(tensor_out%valid)
557 IF (PRESENT(summation)) THEN
558 IF (.NOT. summation) CALL dbt_clear(tensor_out)
559 ELSE
560 CALL dbt_clear(tensor_out)
561 END IF
562
563 DO idim = 1, ndims_tensor(tensor_split_in)
564 CALL get_ith_array(tensor_split_in%blk_sizes, idim, blk_size_split_d)
565 CALL get_ith_array(tensor_out%blk_sizes, idim, blk_size_d)
566
567 IF (idim == 1) THEN
568 ! data offset of split blocks w.r.t. corresponding normal block
569 ALLOCATE (inblock_offset_1(SIZE(blk_size_split_d)))
570 ! normal block index for each split block
571 ALLOCATE (split_1(SIZE(blk_size_split_d)))
572 END IF
573 IF (idim == 2) THEN
574 ! data offset of split blocks w.r.t. corresponding normal block
575 ALLOCATE (inblock_offset_2(SIZE(blk_size_split_d)))
576 ! normal block index for each split block
577 ALLOCATE (split_2(SIZE(blk_size_split_d)))
578 END IF
579 IF (idim == 3) THEN
580 ! data offset of split blocks w.r.t. corresponding normal block
581 ALLOCATE (inblock_offset_3(SIZE(blk_size_split_d)))
582 ! normal block index for each split block
583 ALLOCATE (split_3(SIZE(blk_size_split_d)))
584 END IF
585 IF (idim == 4) THEN
586 ! data offset of split blocks w.r.t. corresponding normal block
587 ALLOCATE (inblock_offset_4(SIZE(blk_size_split_d)))
588 ! normal block index for each split block
589 ALLOCATE (split_4(SIZE(blk_size_split_d)))
590 END IF
591
592 ALLOCATE (last_split_d(SIZE(blk_size_d)))
593 ALLOCATE (first_split_d(SIZE(blk_size_d)))
594 first_split_d(1) = 1
595 isplit_sum = 0
596 DO iblk = 1, SIZE(blk_size_d)
597 splitsum = 0
598 IF (iblk .GT. 1) first_split_d(iblk) = last_split_d(iblk - 1) + 1
599 DO WHILE (splitsum < blk_size_d(iblk))
600 isplit_sum = isplit_sum + 1
601 IF (idim == 1) THEN
602 inblock_offset_1(isplit_sum) = splitsum
603 split_1(isplit_sum) = iblk
604 END IF
605 IF (idim == 2) THEN
606 inblock_offset_2(isplit_sum) = splitsum
607 split_2(isplit_sum) = iblk
608 END IF
609 IF (idim == 3) THEN
610 inblock_offset_3(isplit_sum) = splitsum
611 split_3(isplit_sum) = iblk
612 END IF
613 IF (idim == 4) THEN
614 inblock_offset_4(isplit_sum) = splitsum
615 split_4(isplit_sum) = iblk
616 END IF
617 splitsum = splitsum + blk_size_split_d(isplit_sum)
618 END DO
619 cpassert(splitsum == blk_size_d(iblk))
620 last_split_d(iblk) = isplit_sum
621 END DO
622 IF (idim == 1) THEN
623 ALLOCATE (first_split_1, source=first_split_d)
624 ALLOCATE (last_split_1, source=last_split_d)
625 ALLOCATE (blk_size_split_1, source=blk_size_split_d)
626 END IF
627 IF (idim == 2) THEN
628 ALLOCATE (first_split_2, source=first_split_d)
629 ALLOCATE (last_split_2, source=last_split_d)
630 ALLOCATE (blk_size_split_2, source=blk_size_split_d)
631 END IF
632 IF (idim == 3) THEN
633 ALLOCATE (first_split_3, source=first_split_d)
634 ALLOCATE (last_split_3, source=last_split_d)
635 ALLOCATE (blk_size_split_3, source=blk_size_split_d)
636 END IF
637 IF (idim == 4) THEN
638 ALLOCATE (first_split_4, source=first_split_d)
639 ALLOCATE (last_split_4, source=last_split_d)
640 ALLOCATE (blk_size_split_4, source=blk_size_split_d)
641 END IF
642 DEALLOCATE (first_split_d, last_split_d)
643 DEALLOCATE (blk_size_split_d, blk_size_d)
644 END DO
645
646!$OMP PARALLEL DEFAULT(NONE) &
647!$OMP SHARED(tensor_split_in,tensor_out,summation) &
648!$OMP SHARED(split_1, split_2, split_3, split_4) &
649!$OMP SHARED(first_split_1, first_split_2, first_split_3, first_split_4) &
650!$OMP SHARED(last_split_1, last_split_2, last_split_3, last_split_4) &
651!$OMP SHARED(inblock_offset_1, inblock_offset_2, inblock_offset_3, inblock_offset_4) &
652!$OMP PRIVATE(iter,blks_to_allocate,bcount,blk_index_n) &
653!$OMP PRIVATE(blk_index,blk_size,blk_shape,blk_offset,inblock_offset,found) &
654!$OMP PRIVATE(block_2d,block_3d,block_4d,block_split_2d,block_split_3d,block_split_4d)
655 CALL dbt_iterator_start(iter, tensor_split_in)
656 ALLOCATE (blks_to_allocate(dbt_iterator_num_blocks(iter), ndims_tensor(tensor_split_in)))
657 bcount = 0
658 DO WHILE (dbt_iterator_blocks_left(iter))
659 CALL dbt_iterator_next_block(iter, blk_index, blk_size=blk_size)
660 IF (ndims_tensor(tensor_out) == 2) THEN
661 blk_index_n(1) = split_1(blk_index(1))
662 blk_index_n(2) = split_2(blk_index(2))
663 END IF
664 IF (ndims_tensor(tensor_out) == 3) THEN
665 blk_index_n(1) = split_1(blk_index(1))
666 blk_index_n(2) = split_2(blk_index(2))
667 blk_index_n(3) = split_3(blk_index(3))
668 END IF
669 IF (ndims_tensor(tensor_out) == 4) THEN
670 blk_index_n(1) = split_1(blk_index(1))
671 blk_index_n(2) = split_2(blk_index(2))
672 blk_index_n(3) = split_3(blk_index(3))
673 blk_index_n(4) = split_4(blk_index(4))
674 END IF
675 blks_to_allocate(bcount + 1, :) = blk_index_n
676 bcount = bcount + 1
677 END DO
678 CALL dbt_iterator_stop(iter)
679 CALL dbt_reserve_blocks(tensor_out, blks_to_allocate)
680
681 CALL dbt_iterator_start(iter, tensor_out)
682 DO WHILE (dbt_iterator_blocks_left(iter))
683 CALL dbt_iterator_next_block(iter, blk_index, blk_size=blk_size, blk_offset=blk_offset)
684
685 IF (ndims_tensor(tensor_out) == 2) THEN
686 CALL allocate_any(block_2d, blk_size)
687 block_2d = 0.0_dp
688 DO iblk_1 = first_split_1(blk_index(1)), last_split_1(blk_index(1))
689 DO iblk_2 = first_split_2(blk_index(2)), last_split_2(blk_index(2))
690 inblock_offset(1) = inblock_offset_1(iblk_1)
691 inblock_offset(2) = inblock_offset_2(iblk_2)
692
693 CALL dbt_get_block(tensor_split_in, [iblk_1, iblk_2], &
694 block_split_2d, found)
695 IF (found) THEN
696 blk_shape(1:2) = shape(block_split_2d)
697 block_2d( &
698 inblock_offset(1) + 1:inblock_offset(1) + blk_shape(1), inblock_offset(2) + 1:inblock_offset(2) +&
699 & blk_shape(2)) = &
700 block_split_2d
701 END IF
702
703 END DO
704 END DO
705 CALL dbt_put_block(tensor_out, blk_index, blk_size, block_2d, summation=summation)
706 DEALLOCATE (block_2d)
707 END IF
708 IF (ndims_tensor(tensor_out) == 3) THEN
709 CALL allocate_any(block_3d, blk_size)
710 block_3d = 0.0_dp
711 DO iblk_1 = first_split_1(blk_index(1)), last_split_1(blk_index(1))
712 DO iblk_2 = first_split_2(blk_index(2)), last_split_2(blk_index(2))
713 DO iblk_3 = first_split_3(blk_index(3)), last_split_3(blk_index(3))
714 inblock_offset(1) = inblock_offset_1(iblk_1)
715 inblock_offset(2) = inblock_offset_2(iblk_2)
716 inblock_offset(3) = inblock_offset_3(iblk_3)
717
718 CALL dbt_get_block(tensor_split_in, [iblk_1, iblk_2, iblk_3], &
719 block_split_3d, found)
720 IF (found) THEN
721 blk_shape(1:3) = shape(block_split_3d)
722 block_3d( &
723 inblock_offset(1) + 1:inblock_offset(1) + blk_shape(1), inblock_offset(2) + 1:inblock_offset(2) +&
724 & blk_shape(2), inblock_offset(3) + 1:inblock_offset(3) + blk_shape(3)) = &
725 block_split_3d
726 END IF
727
728 END DO
729 END DO
730 END DO
731 CALL dbt_put_block(tensor_out, blk_index, blk_size, block_3d, summation=summation)
732 DEALLOCATE (block_3d)
733 END IF
734 IF (ndims_tensor(tensor_out) == 4) THEN
735 CALL allocate_any(block_4d, blk_size)
736 block_4d = 0.0_dp
737 DO iblk_1 = first_split_1(blk_index(1)), last_split_1(blk_index(1))
738 DO iblk_2 = first_split_2(blk_index(2)), last_split_2(blk_index(2))
739 DO iblk_3 = first_split_3(blk_index(3)), last_split_3(blk_index(3))
740 DO iblk_4 = first_split_4(blk_index(4)), last_split_4(blk_index(4))
741 inblock_offset(1) = inblock_offset_1(iblk_1)
742 inblock_offset(2) = inblock_offset_2(iblk_2)
743 inblock_offset(3) = inblock_offset_3(iblk_3)
744 inblock_offset(4) = inblock_offset_4(iblk_4)
745
746 CALL dbt_get_block(tensor_split_in, [iblk_1, iblk_2, iblk_3, iblk_4], &
747 block_split_4d, found)
748 IF (found) THEN
749 blk_shape(1:4) = shape(block_split_4d)
750 block_4d( &
751 inblock_offset(1) + 1:inblock_offset(1) + blk_shape(1), inblock_offset(2) + 1:inblock_offset(2) +&
752 & blk_shape(2), inblock_offset(3) + 1:inblock_offset(3) + blk_shape(3), inblock_offset(4) +&
753 & 1:inblock_offset(4) + blk_shape(4)) = &
754 block_split_4d
755 END IF
756
757 END DO
758 END DO
759 END DO
760 END DO
761 CALL dbt_put_block(tensor_out, blk_index, blk_size, block_4d, summation=summation)
762 DEALLOCATE (block_4d)
763 END IF
764 END DO
765 CALL dbt_iterator_stop(iter)
766!$OMP END PARALLEL
767
768 CALL timestop(handle)
769
770 END SUBROUTINE
771
772! **************************************************************************************************
773!> \brief split two tensors with same total sizes but different block sizes such that they have
774!> equal block sizes
775!> \param move_data memory optimization: transfer data s.t. tensor1 and tensor2 may be empty on return
776!> \param tensor1_split tensor 1 with split blocks
777!> \param tensor2_split tensor 2 with split blocks
778!> \param nodata1 don't copy data of tensor 1
779!> \param nodata2 don't copy data of tensor 2
780!> \param
781!> \param
782!> \param
783!> \param
784!> \author Patrick Seewald
785! **************************************************************************************************
786 SUBROUTINE dbt_make_compatible_blocks(tensor1, tensor2, tensor1_split, tensor2_split, &
787 order, nodata1, nodata2, move_data)
788 TYPE(dbt_type), INTENT(INOUT) :: tensor1, tensor2
789 TYPE(dbt_type), INTENT(OUT) :: tensor1_split, tensor2_split
790 INTEGER, DIMENSION(ndims_tensor(tensor1)), &
791 INTENT(IN), OPTIONAL :: order
792 LOGICAL, INTENT(IN), OPTIONAL :: nodata1, nodata2, move_data
793 INTEGER, DIMENSION(:), ALLOCATABLE :: blk_size_split_1_1, blk_size_split_1_2, blk_size_split_1_3,&
794 & blk_size_split_1_4, blk_size_split_2_1, blk_size_split_2_2, blk_size_split_2_3,&
795 & blk_size_split_2_4, &
796 blk_size_d_1, blk_size_d_2, blk_size_d_split
797 INTEGER :: size_sum_1, size_sum_2, size_sum, bind_1, bind_2, isplit, bs, idim, i
798 LOGICAL :: move_prv, nodata1_prv, nodata2_prv
799 INTEGER, DIMENSION(ndims_tensor(tensor1)) :: order_prv
800
801 IF (PRESENT(move_data)) THEN
802 move_prv = move_data
803 ELSE
804 move_prv = .false.
805 END IF
806
807 IF (PRESENT(nodata1)) THEN
808 nodata1_prv = nodata1
809 ELSE
810 nodata1_prv = .false.
811 END IF
812 IF (PRESENT(nodata2)) THEN
813 nodata2_prv = nodata2
814 ELSE
815 nodata2_prv = .false.
816 END IF
817
818 IF (PRESENT(order)) THEN
819 order_prv(:) = dbt_inverse_order(order)
820 ELSE
821 order_prv(:) = (/(i, i=1, ndims_tensor(tensor1))/)
822 END IF
823
824 DO idim = 1, ndims_tensor(tensor2)
825 CALL get_ith_array(tensor1%blk_sizes, order_prv(idim), blk_size_d_1)
826 CALL get_ith_array(tensor2%blk_sizes, idim, blk_size_d_2)
827 ALLOCATE (blk_size_d_split(SIZE(blk_size_d_1) + SIZE(blk_size_d_2)))
828 size_sum_1 = 0
829 size_sum_2 = 0
830 size_sum = 0
831 bind_1 = 0
832 bind_2 = 0
833 isplit = 0
834
835 DO WHILE (bind_1 < SIZE(blk_size_d_1) .AND. bind_2 < SIZE(blk_size_d_2))
836 IF (blk_size_d_1(bind_1 + 1) < blk_size_d_2(bind_2 + 1)) THEN
837 bind_1 = bind_1 + 1
838 bs = blk_size_d_1(bind_1)
839 blk_size_d_2(bind_2 + 1) = blk_size_d_2(bind_2 + 1) - bs
840 size_sum = size_sum + bs
841 isplit = isplit + 1
842 blk_size_d_split(isplit) = bs
843 ELSEIF (blk_size_d_1(bind_1 + 1) > blk_size_d_2(bind_2 + 1)) THEN
844 bind_2 = bind_2 + 1
845 bs = blk_size_d_2(bind_2)
846 blk_size_d_1(bind_1 + 1) = blk_size_d_1(bind_1 + 1) - bs
847 size_sum = size_sum + bs
848 isplit = isplit + 1
849 blk_size_d_split(isplit) = bs
850 ELSE
851 bind_1 = bind_1 + 1
852 bind_2 = bind_2 + 1
853 bs = blk_size_d_1(bind_1)
854 size_sum = size_sum + bs
855 isplit = isplit + 1
856 blk_size_d_split(isplit) = bs
857 END IF
858 END DO
859
860 IF (bind_1 < SIZE(blk_size_d_1)) THEN
861 bind_1 = bind_1 + 1
862 bs = blk_size_d_1(bind_1)
863 size_sum = size_sum + bs
864 isplit = isplit + 1
865 blk_size_d_split(isplit) = bs
866 END IF
867
868 IF (bind_2 < SIZE(blk_size_d_2)) THEN
869 bind_2 = bind_2 + 1
870 bs = blk_size_d_2(bind_2)
871 size_sum = size_sum + bs
872 isplit = isplit + 1
873 blk_size_d_split(isplit) = bs
874 END IF
875
876 IF (order_prv(idim) == 1) THEN
877 ALLOCATE (blk_size_split_1_1, source=blk_size_d_split(:isplit))
878 END IF
879 IF (order_prv(idim) == 2) THEN
880 ALLOCATE (blk_size_split_1_2, source=blk_size_d_split(:isplit))
881 END IF
882 IF (order_prv(idim) == 3) THEN
883 ALLOCATE (blk_size_split_1_3, source=blk_size_d_split(:isplit))
884 END IF
885 IF (order_prv(idim) == 4) THEN
886 ALLOCATE (blk_size_split_1_4, source=blk_size_d_split(:isplit))
887 END IF
888
889 IF (idim == 1) THEN
890 ALLOCATE (blk_size_split_2_1, source=blk_size_d_split(:isplit))
891 END IF
892 IF (idim == 2) THEN
893 ALLOCATE (blk_size_split_2_2, source=blk_size_d_split(:isplit))
894 END IF
895 IF (idim == 3) THEN
896 ALLOCATE (blk_size_split_2_3, source=blk_size_d_split(:isplit))
897 END IF
898 IF (idim == 4) THEN
899 ALLOCATE (blk_size_split_2_4, source=blk_size_d_split(:isplit))
900 END IF
901
902 DEALLOCATE (blk_size_d_split, blk_size_d_1, blk_size_d_2)
903 END DO
904
905 IF (ndims_tensor(tensor1) == 2) THEN
906 CALL dbt_split_blocks_generic(tensor1, tensor1_split, blk_size_split_1_1, blk_size_split_1_2, nodata=nodata1)
907 IF (move_prv .AND. .NOT. nodata1_prv) CALL dbt_clear(tensor1)
908 CALL dbt_split_blocks_generic(tensor2, tensor2_split, blk_size_split_2_1, blk_size_split_2_2, nodata=nodata2)
909 IF (move_prv .AND. .NOT. nodata2_prv) CALL dbt_clear(tensor2)
910 END IF
911 IF (ndims_tensor(tensor1) == 3) THEN
912 CALL dbt_split_blocks_generic(tensor1, tensor1_split, blk_size_split_1_1, blk_size_split_1_2,&
913 & blk_size_split_1_3, nodata=nodata1)
914 IF (move_prv .AND. .NOT. nodata1_prv) CALL dbt_clear(tensor1)
915 CALL dbt_split_blocks_generic(tensor2, tensor2_split, blk_size_split_2_1, blk_size_split_2_2,&
916 & blk_size_split_2_3, nodata=nodata2)
917 IF (move_prv .AND. .NOT. nodata2_prv) CALL dbt_clear(tensor2)
918 END IF
919 IF (ndims_tensor(tensor1) == 4) THEN
920 CALL dbt_split_blocks_generic(tensor1, tensor1_split, blk_size_split_1_1, blk_size_split_1_2,&
921 & blk_size_split_1_3, blk_size_split_1_4, nodata=nodata1)
922 IF (move_prv .AND. .NOT. nodata1_prv) CALL dbt_clear(tensor1)
923 CALL dbt_split_blocks_generic(tensor2, tensor2_split, blk_size_split_2_1, blk_size_split_2_2,&
924 & blk_size_split_2_3, blk_size_split_2_4, nodata=nodata2)
925 IF (move_prv .AND. .NOT. nodata2_prv) CALL dbt_clear(tensor2)
926 END IF
927
928 END SUBROUTINE
929
930! **************************************************************************************************
931!> \author Patrick Seewald
932! **************************************************************************************************
933 SUBROUTINE dbt_crop(tensor_in, tensor_out, bounds, move_data)
934 TYPE(dbt_type), INTENT(INOUT) :: tensor_in
935 TYPE(dbt_type), INTENT(OUT) :: tensor_out
936 INTEGER, DIMENSION(2, ndims_tensor(tensor_in)), INTENT(IN) :: bounds
937 LOGICAL, INTENT(IN), OPTIONAL :: move_data
938
939 CHARACTER(LEN=*), PARAMETER :: routinen = 'dbt_crop'
940
941 INTEGER, DIMENSION(2, ndims_tensor(tensor_in)) :: blk_bounds
942 TYPE(dbt_iterator_type) :: iter
943 INTEGER, DIMENSION(ndims_tensor(tensor_in)) :: blk_index, blk_size, blk_offset
944 LOGICAL :: found, move_data_prv
945 INTEGER :: handle, idim, iblk_out
946 INTEGER, DIMENSION(:, :), ALLOCATABLE :: blk_ind_out
947 REAL(dp), DIMENSION(:,:), ALLOCATABLE :: block_2d, block_put_2d
948 REAL(dp), DIMENSION(:,:,:), ALLOCATABLE :: block_3d, block_put_3d
949 REAL(dp), DIMENSION(:,:,:,:), ALLOCATABLE :: block_4d, block_put_4d
950
951 CALL timeset(routinen, handle)
952
953 IF (PRESENT(move_data)) THEN
954 move_data_prv = move_data
955 ELSE
956 move_data_prv = .false.
957 END IF
958
959 CALL dbt_create(tensor_in, tensor_out)
960
961!$OMP PARALLEL DEFAULT(NONE) SHARED(tensor_in,tensor_out,bounds) &
962!$OMP PRIVATE(iter,blk_ind_out,iblk_out,blk_index,blk_size,blk_offset,found,blk_bounds) &
963!$OMP PRIVATE(block_2d,block_put_2d,block_3d,block_put_3d,block_4d,block_put_4d)
964
965 ! reserve blocks inside bounds
966 CALL dbt_iterator_start(iter, tensor_in)
967 ALLOCATE (blk_ind_out(dbt_iterator_num_blocks(iter), ndims_tensor(tensor_in)))
968 blk_ind_out(:, :) = 0
969 iblk_out = 0
970 blk_loop: DO WHILE (dbt_iterator_blocks_left(iter))
971 CALL dbt_iterator_next_block(iter, blk_index, blk_size=blk_size, blk_offset=blk_offset)
972 DO idim = 1, ndims_tensor(tensor_in)
973 IF (bounds(1, idim) > blk_offset(idim) - 1 + blk_size(idim)) cycle blk_loop
974 IF (bounds(2, idim) < blk_offset(idim)) cycle blk_loop
975 END DO
976 iblk_out = iblk_out + 1
977 blk_ind_out(iblk_out, :) = blk_index
978 END DO blk_loop
979 CALL dbt_iterator_stop(iter)
980
981 CALL dbt_reserve_blocks(tensor_out, blk_ind_out(1:iblk_out, :))
982 DEALLOCATE (blk_ind_out)
983
984 ! copy blocks
985 CALL dbt_iterator_start(iter, tensor_out)
986 iter_loop: DO WHILE (dbt_iterator_blocks_left(iter))
987 CALL dbt_iterator_next_block(iter, blk_index, blk_size=blk_size, blk_offset=blk_offset)
988
989 DO idim = 1, ndims_tensor(tensor_in)
990 blk_bounds(1, idim) = max(bounds(1, idim) - blk_offset(idim) + 1, 1)
991 blk_bounds(2, idim) = min(bounds(2, idim) - blk_offset(idim) + 1, blk_size(idim))
992 END DO
993
994 IF (ndims_tensor(tensor_in) == 2) THEN
995 CALL dbt_get_block(tensor_in, blk_index, block_2d, found)
996
997 ALLOCATE (block_put_2d(blk_size(1), blk_size(2)))
998 block_put_2d = 0.0_dp
999 block_put_2d(blk_bounds(1, 1):blk_bounds(2,1), blk_bounds(1, 2):blk_bounds(2,2)) = &
1000 block_2d(blk_bounds(1, 1):blk_bounds(2,1), blk_bounds(1, 2):blk_bounds(2,2))
1001 CALL dbt_put_block(tensor_out, blk_index, blk_size, block_put_2d)
1002 DEALLOCATE (block_2d)
1003 DEALLOCATE (block_put_2d)
1004 END IF
1005 IF (ndims_tensor(tensor_in) == 3) THEN
1006 CALL dbt_get_block(tensor_in, blk_index, block_3d, found)
1007
1008 ALLOCATE (block_put_3d(blk_size(1), blk_size(2), blk_size(3)))
1009 block_put_3d = 0.0_dp
1010 block_put_3d(blk_bounds(1, 1):blk_bounds(2,1), blk_bounds(1, 2):blk_bounds(2,2), blk_bounds(1, 3):blk_bounds(2,3)) = &
1011 block_3d(blk_bounds(1, 1):blk_bounds(2,1), blk_bounds(1, 2):blk_bounds(2,2), blk_bounds(1, 3):blk_bounds(2,3))
1012 CALL dbt_put_block(tensor_out, blk_index, blk_size, block_put_3d)
1013 DEALLOCATE (block_3d)
1014 DEALLOCATE (block_put_3d)
1015 END IF
1016 IF (ndims_tensor(tensor_in) == 4) THEN
1017 CALL dbt_get_block(tensor_in, blk_index, block_4d, found)
1018
1019 ALLOCATE (block_put_4d(blk_size(1), blk_size(2), blk_size(3), blk_size(4)))
1020 block_put_4d = 0.0_dp
1021 block_put_4d(blk_bounds(1, 1):blk_bounds(2,1), blk_bounds(1, 2):blk_bounds(2,2), blk_bounds(1, 3):blk_bounds(2,3),&
1022 & blk_bounds(1, 4):blk_bounds(2,4)) = &
1023 block_4d(blk_bounds(1, 1):blk_bounds(2,1), blk_bounds(1, 2):blk_bounds(2,2), blk_bounds(1, 3):blk_bounds(2,3),&
1024 & blk_bounds(1, 4):blk_bounds(2,4))
1025 CALL dbt_put_block(tensor_out, blk_index, blk_size, block_put_4d)
1026 DEALLOCATE (block_4d)
1027 DEALLOCATE (block_put_4d)
1028 END IF
1029 END DO iter_loop
1030 CALL dbt_iterator_stop(iter)
1031!$OMP END PARALLEL
1032 CALL dbt_finalize(tensor_out)
1033
1034 IF (move_data_prv) CALL dbt_clear(tensor_in)
1035
1036 ! transfer data for batched contraction
1037 CALL dbt_copy_contraction_storage(tensor_in, tensor_out)
1038
1039 CALL timestop(handle)
1040 END SUBROUTINE
1041
1042 END MODULE
Wrapper for allocating, copying and reshaping arrays.
Representation of arbitrary number of 1d integer arrays with arbitrary sizes. This is needed for gene...
Methods to operate on n-dimensional tensor blocks.
Definition dbt_block.F:12
integer function, public dbt_iterator_num_blocks(iterator)
Generalization of block_iterator_num_blocks for tensors.
Definition dbt_block.F:185
logical function, public dbt_iterator_blocks_left(iterator)
Generalization of block_iterator_blocks_left for tensors.
Definition dbt_block.F:197
subroutine, public dbt_iterator_stop(iterator)
Generalization of block_iterator_stop for tensors.
Definition dbt_block.F:134
subroutine, public dbt_iterator_start(iterator, tensor)
Generalization of block_iterator_start for tensors.
Definition dbt_block.F:121
subroutine, public dbt_iterator_next_block(iterator, ind_nd, blk_size, blk_offset)
iterate over nd blocks of an nd rank tensor, index only (blocks must be retrieved by calling dbt_get_...
Definition dbt_block.F:161
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
pure subroutine, public dbt_get_mapping_info(map, ndim_nd, ndim1_2d, ndim2_2d, dims_2d_i8, dims_2d, dims_nd, dims1_2d, dims2_2d, map1_2d, map2_2d, map_nd, base, col_major)
get mapping info
Definition dbt_index.F:176
Routines to split blocks and to convert between tensors with different block sizes.
Definition dbt_split.F:12
subroutine, public dbt_split_blocks(tensor_in, tensor_out, block_sizes, nodata)
Split tensor blocks into smaller blocks of maximum size PRODUCT(block_sizes).
Definition dbt_split.F:455
subroutine, public dbt_split_copyback(tensor_split_in, tensor_out, summation)
Copy tensor with split blocks to tensor with original block sizes.
Definition dbt_split.F:527
subroutine, public dbt_make_compatible_blocks(tensor1, tensor2, tensor1_split, tensor2_split, order, nodata1, nodata2, move_data)
split two tensors with same total sizes but different block sizes such that they have equal block siz...
Definition dbt_split.F:788
subroutine, public dbt_split_blocks_generic(tensor_in, tensor_out, blk_size_1, blk_size_2, blk_size_3, blk_size_4, nodata)
Split tensor blocks into smaller blocks.
Definition dbt_split.F:69
subroutine, public dbt_crop(tensor_in, tensor_out, bounds, move_data)
Definition dbt_split.F:934
DBT tensor framework for block-sparse tensor contraction: Types and create/destroy routines.
Definition dbt_types.F:12
subroutine, public dbt_copy_contraction_storage(tensor_in, tensor_out)
Definition dbt_types.F:1888
subroutine, public dbt_blk_sizes(tensor, ind, blk_size)
Size of tensor block.
Definition dbt_types.F:1479
subroutine, public dbt_distribution_new_expert(dist, pgrid, map1_2d, map2_2d, nd_dist_1, nd_dist_2, nd_dist_3, nd_dist_4, own_comm)
Create a tensor distribution.
Definition dbt_types.F:787
type(dbt_distribution_type) function, public dbt_distribution(tensor)
get distribution from tensor
Definition dbt_types.F:980
pure integer function, public ndims_tensor(tensor)
tensor rank
Definition dbt_types.F:1227
pure integer function, public dbt_get_num_blocks(tensor)
As block_get_num_blocks: get number of local blocks.
Definition dbt_types.F:1759
subroutine, public dbt_clear(tensor)
Clear tensor (s.t. it does not contain any blocks)
Definition dbt_types.F:1779
subroutine, public dbt_finalize(tensor)
Finalize tensor, as block_finalize. This should be taken care of internally in DBT tensors,...
Definition dbt_types.F:1790
pure integer(int_8) function, public ndims_matrix_row(tensor)
how many tensor dimensions are mapped to matrix row
Definition dbt_types.F:1204
pure integer(int_8) function, public ndims_matrix_column(tensor)
how many tensor dimensions are mapped to matrix column
Definition dbt_types.F:1216
subroutine, public dbt_blk_offsets(tensor, ind, blk_offset)
offset of tensor block
Definition dbt_types.F:1495
subroutine, public dbt_filter(tensor, eps)
As block_filter.
Definition dbt_types.F:1588
subroutine, public dbt_distribution_destroy(dist)
Destroy tensor distribution.
Definition dbt_types.F:926
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34