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 : ! **************************************************************************************************
9 : !> \par History
10 : !> JGH (30-Nov-2000): ESSL FFT Library added
11 : !> JGH (05-Jan-2001): Added SGI library FFT
12 : !> JGH (14-Jan-2001): Added parallel 3d FFT
13 : !> JGH (10-Feb-2006): New interface type
14 : !> JGH (31-Mar-2008): Remove local allocates and reshapes (performance)
15 : !> Possible problems can be related with setting arrays
16 : !> not to zero
17 : !> Some interfaces could be further simplified by avoiding
18 : !> an initial copy. However, this assumes contiguous arrays
19 : !> IAB (15-Oct-2008): Moved mp_cart_sub calls out of cube_tranpose_* and into
20 : !> fft_scratch type, reducing number of calls dramatically
21 : !> IAB (05-Dec-2008): Moved all other non-essential MPI calls into scratch type
22 : !> IAB (09-Jan-2009): Added fft_plan_type to store FFT data, including cached FFTW plans
23 : !> IAB (13-Feb-2009): Extended plan caching to serial 3D FFT (fft3d_s)
24 : !> IAB (09-Oct-2009): Added OpenMP directives to parallel 3D FFT
25 : !> (c) The Numerical Algorithms Group (NAG) Ltd, 2008-2009 on behalf of the HECToR project
26 : !> HFP (17-Oct-2024): Thread-safety insurance (CPASSERT), and OMP ATOMIC (tick_fft_pool)
27 : !> \author JGH
28 : ! **************************************************************************************************
29 : MODULE fft_tools
30 : USE ISO_C_BINDING, ONLY: C_F_POINTER,&
31 : C_LOC,&
32 : C_PTR,&
33 : C_SIZE_T
34 : USE cp_log_handling, ONLY: cp_logger_get_default_io_unit
35 : USE fft_lib, ONLY: &
36 : fft_1d, fft_3d, fft_alloc, fft_create_plan_1d, fft_create_plan_3d, fft_dealloc, &
37 : fft_destroy_plan, fft_do_cleanup, fft_do_init, fft_get_lengths
38 : USE fft_plan, ONLY: fft_plan_type
39 : USE kinds, ONLY: dp,&
40 : dp_size,&
41 : sp
42 : USE mathconstants, ONLY: z_zero
43 : USE message_passing, ONLY: mp_cart_type,&
44 : mp_comm_null,&
45 : mp_comm_type,&
46 : mp_request_type,&
47 : mp_waitall
48 : USE offload_api, ONLY: offload_free_pinned_mem,&
49 : offload_malloc_pinned_mem
50 :
51 : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num, omp_in_parallel
52 :
53 : #include "../base/base_uses.f90"
54 :
55 : IMPLICIT NONE
56 :
57 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'fft_tools'
58 :
59 : ! Types for the pool of scratch data needed in FFT routines
60 : ! keep the subroutine "is_equal" up-to-date
61 : ! needs a default initialization
62 : TYPE fft_scratch_sizes
63 : INTEGER :: nx = 0, ny = 0, nz = 0
64 : INTEGER :: lmax = 0, mmax = 0, nmax = 0
65 : INTEGER :: mx1 = 0, mx2 = 0, mx3 = 0
66 : INTEGER :: my1 = 0, my2 = 0, my3 = 0
67 : INTEGER :: mz1 = 0, mz2 = 0, mz3 = 0
68 : INTEGER :: mcz1 = 0, mcz2 = 0, mcy3 = 0, mcx2 = 0
69 : INTEGER :: lg = 0, mg = 0
70 : INTEGER :: nbx = 0, nbz = 0
71 : INTEGER :: nmray = 0, nyzray = 0
72 : TYPE(mp_cart_type) :: rs_group = mp_cart_type()
73 : INTEGER, DIMENSION(2) :: g_pos = 0, r_pos = 0, r_dim = 0
74 : INTEGER :: numtask = 0
75 : END TYPE fft_scratch_sizes
76 :
77 : TYPE fft_scratch_type
78 : INTEGER :: fft_scratch_id = 0
79 : INTEGER :: tf_type = -1
80 : LOGICAL :: in_use = .TRUE.
81 : TYPE(mp_comm_type) :: group = mp_comm_type()
82 : INTEGER, DIMENSION(3) :: nfft = -1
83 : ! to be used in cube_transpose_* routines
84 : TYPE(mp_cart_type), DIMENSION(2) :: cart_sub_comm = mp_cart_type()
85 : INTEGER, DIMENSION(2) :: dim = -1, pos = -1
86 : ! to be used in fft3d_s
87 : COMPLEX(KIND=dp), DIMENSION(:, :, :), POINTER, CONTIGUOUS &
88 : :: ziptr => NULL(), zoptr => NULL()
89 : ! to be used in fft3d_ps : block distribution
90 : COMPLEX(KIND=dp), DIMENSION(:, :), CONTIGUOUS, POINTER &
91 : :: p1buf => NULL(), p2buf => NULL(), p3buf => NULL(), p4buf => NULL(), &
92 : p5buf => NULL(), p6buf => NULL(), p7buf => NULL()
93 : ! to be used in fft3d_ps : plane distribution
94 : COMPLEX(KIND=dp), DIMENSION(:, :), POINTER, CONTIGUOUS &
95 : :: r1buf => NULL(), r2buf => NULL()
96 : COMPLEX(KIND=dp), DIMENSION(:, :, :), POINTER, CONTIGUOUS &
97 : :: tbuf => NULL()
98 : ! to be used in fft3d_pb
99 : COMPLEX(KIND=dp), DIMENSION(:, :), POINTER, CONTIGUOUS &
100 : :: a1buf => NULL(), a2buf => NULL(), a3buf => NULL(), &
101 : a4buf => NULL(), a5buf => NULL(), a6buf => NULL()
102 : ! to be used in communication routines
103 : INTEGER, DIMENSION(:), CONTIGUOUS, POINTER :: scount => NULL(), rcount => NULL(), sdispl => NULL(), rdispl => NULL()
104 : INTEGER, DIMENSION(:, :), CONTIGUOUS, POINTER :: pgcube => NULL()
105 : INTEGER, DIMENSION(:), CONTIGUOUS, POINTER :: xzcount => NULL(), yzcount => NULL(), xzdispl => NULL(), yzdispl => NULL()
106 : INTEGER :: in = 0, mip = -1
107 : REAL(KIND=dp) :: rsratio = 1.0_dp
108 : COMPLEX(KIND=dp), DIMENSION(:), POINTER, CONTIGUOUS &
109 : :: xzbuf => NULL(), yzbuf => NULL()
110 : COMPLEX(KIND=sp), DIMENSION(:), POINTER, CONTIGUOUS &
111 : :: xzbuf_sgl => NULL(), yzbuf_sgl => NULL()
112 : COMPLEX(KIND=dp), DIMENSION(:, :), POINTER, CONTIGUOUS &
113 : :: rbuf1 => NULL(), rbuf2 => NULL(), rbuf3 => NULL(), rbuf4 => NULL(), &
114 : rbuf5 => NULL(), rbuf6 => NULL(), rr => NULL()
115 : COMPLEX(KIND=sp), DIMENSION(:, :), POINTER, CONTIGUOUS &
116 : :: ss => NULL(), tt => NULL()
117 : INTEGER, DIMENSION(:, :), POINTER, CONTIGUOUS :: pgrid => NULL()
118 : INTEGER, DIMENSION(:), POINTER, CONTIGUOUS :: xcor => NULL(), zcor => NULL(), pzcoord => NULL()
119 : TYPE(fft_scratch_sizes) :: sizes = fft_scratch_sizes()
120 : TYPE(fft_plan_type), DIMENSION(6) :: fft_plan = fft_plan_type()
121 : INTEGER :: last_tick = -1
122 : END TYPE fft_scratch_type
123 :
124 : TYPE fft_scratch_pool_type
125 : TYPE(fft_scratch_type), POINTER :: fft_scratch => NULL()
126 : TYPE(fft_scratch_pool_type), POINTER :: fft_scratch_next => NULL()
127 : END TYPE fft_scratch_pool_type
128 :
129 : INTEGER, SAVE :: init_fft_pool = 0
130 : ! the clock for fft pool. Allows to identify the least recently used scratch
131 : INTEGER, SAVE :: tick_fft_pool = 0
132 : ! limit the number of scratch pools to fft_pool_scratch_limit.
133 : INTEGER, SAVE :: fft_pool_scratch_limit = 15
134 : TYPE(fft_scratch_pool_type), POINTER, SAVE :: fft_scratch_first
135 : ! END of types for the pool of scratch data needed in FFT routines
136 :
137 : PRIVATE
138 : PUBLIC :: init_fft, fft3d, finalize_fft
139 : PUBLIC :: fft_alloc, fft_dealloc
140 : PUBLIC :: init_fft_scratch_pool
141 : PUBLIC :: fft_radix_operations, fft_1d_many
142 : PUBLIC :: FWFFT, BWFFT
143 : PUBLIC :: FFT_RADIX_CLOSEST, FFT_RADIX_NEXT
144 : PUBLIC :: FFT_RADIX_NEXT_ODD
145 :
146 : INTEGER, PARAMETER :: FWFFT = +1, BWFFT = -1
147 : INTEGER, PARAMETER :: FFT_RADIX_CLOSEST = 493, FFT_RADIX_NEXT = 494
148 : INTEGER, PARAMETER :: FFT_RADIX_ALLOWED = 495, FFT_RADIX_DISALLOWED = 496
149 : INTEGER, PARAMETER :: FFT_RADIX_NEXT_ODD = 497
150 :
151 : REAL(KIND=dp), PARAMETER :: ratio_sparse_alltoall = 0.5_dp
152 :
153 : ! these saved variables are FFT globals
154 : LOGICAL, SAVE :: alltoall_sgl = .FALSE.
155 :
156 : ! these are only needed for pw_gpu (-D__OFFLOAD)
157 : PUBLIC :: get_fft_scratch, release_fft_scratch
158 : PUBLIC :: cube_transpose_1, cube_transpose_2
159 : PUBLIC :: yz_to_x, x_to_yz, xz_to_yz, yz_to_xz
160 : PUBLIC :: fft_scratch_sizes, fft_scratch_type
161 :
162 : INTERFACE fft3d
163 : MODULE PROCEDURE fft3d_s, fft3d_ps, fft3d_pb
164 : END INTERFACE
165 :
166 : ! **************************************************************************************************
167 :
168 : CONTAINS
169 :
170 : ! **************************************************************************************************
171 : !> \brief ...
172 : !> \param fftlib ...
173 : !> \param alltoall ...
174 : !> \param pool_limit ...
175 : !> \param wisdom_file ...
176 : !> \param plan_style ...
177 : !> \author JGH
178 : ! **************************************************************************************************
179 11603 : SUBROUTINE init_fft(fftlib, alltoall, pool_limit, wisdom_file, &
180 : plan_style)
181 :
182 : CHARACTER(LEN=*), INTENT(IN) :: fftlib
183 : LOGICAL, INTENT(IN) :: alltoall
184 : INTEGER, INTENT(IN) :: pool_limit
185 : CHARACTER(LEN=*), INTENT(IN) :: wisdom_file
186 : INTEGER, INTENT(IN) :: plan_style
187 :
188 11603 : alltoall_sgl = alltoall
189 11603 : fft_pool_scratch_limit = pool_limit
190 :
191 11603 : CALL release_fft_scratch_pool()
192 :
193 11603 : CALL fft_do_init(fftlib, plan_style, wisdom_file)
194 :
195 : ! setup the FFT scratch pool, if one is associated, clear first
196 11603 : CALL init_fft_scratch_pool()
197 :
198 11603 : END SUBROUTINE init_fft
199 :
200 : ! **************************************************************************************************
201 : !> \brief does whatever is needed to finalize the current fft setup
202 : !> \param para_env ...
203 : !> \param wisdom_file ...
204 : !> \par History
205 : !> 10.2007 created [Joost VandeVondele]
206 : ! **************************************************************************************************
207 11393 : SUBROUTINE finalize_fft(para_env, wisdom_file)
208 : CLASS(mp_comm_type) :: para_env
209 : CHARACTER(LEN=*), INTENT(IN) :: wisdom_file
210 :
211 : ! release the FFT scratch pool
212 :
213 11393 : CALL release_fft_scratch_pool()
214 :
215 : ! finalize fft libs
216 :
217 11393 : CALL fft_do_cleanup(wisdom_file, para_env%is_source())
218 :
219 11393 : END SUBROUTINE finalize_fft
220 :
221 : ! **************************************************************************************************
222 : !> \brief Determine the allowed lengths of FFT's '''
223 : !> \param radix_in ...
224 : !> \param radix_out ...
225 : !> \param operation ...
226 : !> \par History
227 : !> new library structure (JGH)
228 : !> \author Ari Seitsonen
229 : ! **************************************************************************************************
230 269191 : SUBROUTINE fft_radix_operations(radix_in, radix_out, operation)
231 :
232 : INTEGER, INTENT(IN) :: radix_in
233 : INTEGER, INTENT(OUT) :: radix_out
234 : INTEGER, INTENT(IN) :: operation
235 :
236 : INTEGER, PARAMETER :: number_of_small_radices = 81
237 : INTEGER, DIMENSION(number_of_small_radices), PARAMETER :: small_radices = [2, 4, 6, 8, 9, 12,&
238 : 15, 16, 18, 20, 24, 25, 27, 30, 32, 36, 40, 45, 48, 54, 60, 64, 72, 75, 80, 81, 90, 96, &
239 : 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192, 200, 216, 225, 240, 243, 256, &
240 : 270, 288, 300, 320, 324, 360, 375, 384, 400, 405, 432, 450, 480, 486, 500, 512, 540, 576, &
241 : 600, 625, 640, 648, 675, 720, 729, 750, 768, 800, 810, 864, 900, 960, 972, 1000, 1024]
242 :
243 : INTEGER :: i, iloc, ldata, trial_number
244 269191 : INTEGER, ALLOCATABLE, DIMENSION(:) :: DATA
245 :
246 269191 : ldata = 1024
247 269191 : ALLOCATE (DATA(ldata))
248 275920775 : DATA = -1
249 :
250 22073662 : DATA(1:number_of_small_radices) = small_radices(1:number_of_small_radices)
251 :
252 : ! First run: try smaller radices
253 : ! Second run: Fetch extended list of radices and try these
254 269191 : DO trial_number = 1, 2
255 269191 : IF (trial_number == 2) CALL fft_get_lengths(DATA, ldata)
256 269191 : iloc = 0
257 3465865 : DO i = 1, ldata
258 3465865 : IF (DATA(i) == radix_in) THEN
259 : iloc = i
260 : EXIT
261 : ELSE
262 3320319 : IF (OPERATION == FFT_RADIX_ALLOWED) THEN
263 : CYCLE
264 3320319 : ELSE IF (DATA(i) > radix_in) THEN
265 : iloc = i
266 : EXIT
267 : END IF
268 : END IF
269 : END DO
270 :
271 269191 : IF (iloc == 0) THEN
272 0 : IF (trial_number == 1) THEN
273 : ! We haven't found any suitable size in the list of smaller radices
274 : ! because the requested radix is too large (large cell or large cutoff)
275 : ! So, try again with the larger radices
276 : CYCLE
277 : ELSE
278 0 : IF (OPERATION == FFT_RADIX_CLOSEST) THEN
279 0 : radix_out = MAXVAL(DATA)
280 : ELSE
281 : CALL cp_abort(__LOCATION__, &
282 0 : "No suitable FFT lengths found! Either enable FFTW or reduce the grid size!")
283 : END IF
284 0 : RETURN
285 : END IF
286 :
287 : END IF
288 :
289 269191 : IF (OPERATION == FFT_RADIX_ALLOWED) THEN
290 0 : IF (DATA(iloc) == radix_in) THEN
291 0 : radix_out = FFT_RADIX_ALLOWED
292 : ELSE
293 0 : radix_out = FFT_RADIX_DISALLOWED
294 : END IF
295 :
296 269191 : ELSE IF (OPERATION == FFT_RADIX_CLOSEST) THEN
297 288 : IF (DATA(iloc) == radix_in) THEN
298 120 : radix_out = DATA(iloc)
299 : ELSE
300 168 : IF (ABS(DATA(iloc - 1) - radix_in) <= &
301 : ABS(DATA(iloc) - radix_in)) THEN
302 162 : radix_out = DATA(iloc - 1)
303 : ELSE
304 6 : radix_out = DATA(iloc)
305 : END IF
306 : END IF
307 :
308 268903 : ELSE IF (OPERATION == FFT_RADIX_NEXT) THEN
309 266881 : radix_out = DATA(iloc)
310 :
311 2022 : ELSE IF (OPERATION == FFT_RADIX_NEXT_ODD) THEN
312 3476 : DO i = iloc, ldata
313 3476 : IF (MOD(DATA(i), 2) == 1) THEN
314 2022 : radix_out = DATA(i)
315 2022 : EXIT
316 : END IF
317 : END DO
318 2022 : IF (MOD(radix_out, 2) == 0) THEN
319 : ! No larger odd radix found
320 0 : IF (trial_number == 1) THEN
321 : CYCLE
322 : ELSE
323 0 : radix_out = radix_in + 1 - MOD(radix_in, 2)
324 : END IF
325 : END IF
326 :
327 : END IF
328 0 : EXIT
329 : END DO
330 :
331 269191 : DEALLOCATE (DATA)
332 :
333 0 : END SUBROUTINE fft_radix_operations
334 :
335 : ! **************************************************************************************************
336 : !> \brief Performs m 1-D forward FFT-s of size n.
337 : !> \param sign ...
338 : !> \param n size of the FFT
339 : !> \param m number of FFT-s
340 : !> \param trans_in transposition state of the input array
341 : !> \param trans_out transposition state of the output array
342 : !> \param ldx_in ...
343 : !> \param ldx_out ...
344 : !> \param zin input array
345 : !> \param zout output array
346 : !> \param scale scaling factor
347 : !> \param stat status of the operation, non-zero code indicates an error
348 : ! **************************************************************************************************
349 1884 : SUBROUTINE fft_1d_many(sign, n, m, trans_in, trans_out, ldx_in, ldx_out, zin, zout, scale, stat)
350 : INTEGER, INTENT(in) :: sign, n, m
351 : LOGICAL, INTENT(in) :: trans_in, trans_out
352 : INTEGER, INTENT(in) :: ldx_in, ldx_out
353 : COMPLEX(kind=dp), DIMENSION(*), INTENT(inout) :: zin, zout
354 : REAL(kind=dp), INTENT(in) :: scale
355 : INTEGER, INTENT(out) :: stat
356 :
357 : CHARACTER(len=*), PARAMETER :: routineN = 'fft_1d_many'
358 :
359 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:), &
360 1884 : POINTER :: ztmp
361 : INTEGER :: handle
362 : TYPE(fft_plan_type) :: fft_plan
363 :
364 1884 : CALL timeset(routineN, handle)
365 :
366 1884 : IF (sign /= FWFFT .AND. sign /= BWFFT) THEN
367 0 : CPABORT("Unknown FFT-direction!")
368 : END IF
369 :
370 1884 : NULLIFY (ztmp)
371 1884 : IF (trans_in) THEN
372 0 : CALL fft_alloc(ztmp, [ldx_in*n])
373 : ELSE
374 3768 : CALL fft_alloc(ztmp, [ldx_in*m])
375 : END IF
376 1884 : CALL fft_create_plan_1d(fft_plan, sign, trans_in, trans_out, ldx_in, ldx_out, n, m, ztmp, zout)
377 1884 : CALL fft_dealloc(ztmp)
378 1884 : CALL fft_1d(fft_plan, zin, zout, scale, stat)
379 1884 : CALL fft_destroy_plan(fft_plan)
380 :
381 1884 : CALL timestop(handle)
382 7536 : END SUBROUTINE fft_1d_many
383 :
384 : ! **************************************************************************************************
385 : !> \brief Calls the 3D-FFT function from the initialized library
386 : !> \param fsign ...
387 : !> \param n ...
388 : !> \param zin ...
389 : !> \param zout ...
390 : !> \param status ...
391 : !> \param debug ...
392 : !> \par History
393 : !> none
394 : !> \author JGH
395 : ! **************************************************************************************************
396 678145 : SUBROUTINE fft3d_s(fsign, n, zin, zout, status, debug)
397 :
398 : INTEGER, INTENT(IN) :: fsign
399 : INTEGER, DIMENSION(:), INTENT(INOUT) :: n
400 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :, :), &
401 : INTENT(INOUT) :: zin
402 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :, :), &
403 : INTENT(INOUT), OPTIONAL, TARGET :: zout
404 : INTEGER, INTENT(OUT), OPTIONAL :: status
405 : LOGICAL, INTENT(IN), OPTIONAL :: debug
406 :
407 : CHARACTER(len=*), PARAMETER :: routineN = 'fft3d_s'
408 :
409 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :, :), &
410 678145 : POINTER :: zoptr
411 : COMPLEX(KIND=dp), DIMENSION(1, 1, 1), TARGET :: zdum
412 : INTEGER :: handle, ld(3), lo(3), output_unit, sign, &
413 : stat
414 : LOGICAL :: fft_in_place, test
415 : REAL(KIND=dp) :: in_sum, norm, out_sum
416 : TYPE(fft_scratch_type), POINTER :: fft_scratch
417 :
418 678145 : CALL timeset(routineN, handle)
419 678145 : output_unit = cp_logger_get_default_io_unit()
420 :
421 678145 : IF (fsign == FWFFT) THEN
422 1274016 : norm = 1.0_dp/REAL(PRODUCT(n), KIND=dp)
423 359641 : ELSE IF (fsign == BWFFT) THEN
424 359641 : norm = 1.0_dp
425 : ELSE
426 0 : CPABORT("Unknown FFT direction!")
427 : END IF
428 :
429 678145 : IF (PRESENT(debug)) THEN
430 618424 : test = debug
431 : ELSE
432 : test = .FALSE.
433 : END IF
434 :
435 678145 : IF (PRESENT(zout)) THEN
436 : fft_in_place = .FALSE.
437 : ELSE
438 670443 : fft_in_place = .TRUE.
439 : END IF
440 :
441 678145 : IF (test) THEN
442 0 : in_sum = SUM(ABS(zin))
443 : END IF
444 :
445 678145 : ld(1) = SIZE(zin, 1)
446 678145 : ld(2) = SIZE(zin, 2)
447 678145 : ld(3) = SIZE(zin, 3)
448 :
449 678145 : IF (n(1) /= ld(1) .OR. n(2) /= ld(2) .OR. n(3) /= ld(3)) THEN
450 0 : CPABORT("Size and dimension (zin) have to be the same.")
451 : END IF
452 :
453 678145 : sign = fsign
454 678145 : CALL get_fft_scratch(fft_scratch, tf_type=400, n=n)
455 :
456 678145 : IF (fft_in_place) THEN
457 670443 : zoptr => zdum
458 670443 : IF (fsign == FWFFT) THEN
459 313268 : CALL fft_3d(fft_scratch%fft_plan(1), norm, zin, zoptr, stat)
460 : ELSE
461 357175 : CALL fft_3d(fft_scratch%fft_plan(2), norm, zin, zoptr, stat)
462 : END IF
463 : ELSE
464 7702 : IF (fsign == FWFFT) THEN
465 5236 : CALL fft_3d(fft_scratch%fft_plan(3), norm, zin, zout, stat)
466 : ELSE
467 2466 : CALL fft_3d(fft_scratch%fft_plan(4), norm, zin, zout, stat)
468 : END IF
469 : END IF
470 :
471 678145 : CALL release_fft_scratch(fft_scratch)
472 :
473 678145 : IF (PRESENT(zout)) THEN
474 7702 : lo(1) = SIZE(zout, 1)
475 7702 : lo(2) = SIZE(zout, 2)
476 7702 : lo(3) = SIZE(zout, 3)
477 7702 : IF (n(1) /= lo(1) .OR. n(2) /= lo(2) .OR. n(3) /= lo(3)) THEN
478 0 : CPABORT("Size and dimension (zout) have to be the same.")
479 : END IF
480 : END IF
481 :
482 678145 : IF (PRESENT(status)) THEN
483 19283 : status = stat
484 : END IF
485 :
486 678145 : IF (test .AND. output_unit > 0) THEN
487 0 : IF (PRESENT(zout)) THEN
488 0 : out_sum = SUM(ABS(zout))
489 0 : WRITE (output_unit, '(A)') " Out of place 3D FFT (local) : fft3d_s"
490 0 : WRITE (output_unit, '(A,T60,3I7)') " Transform lengths ", n
491 0 : WRITE (output_unit, '(A,T60,3I7)') " Input array dimensions ", ld
492 0 : WRITE (output_unit, '(A,T60,3I7)') " Output array dimensions ", lo
493 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of input data ", in_sum
494 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of output data ", out_sum
495 : ELSE
496 0 : out_sum = SUM(ABS(zin))
497 0 : WRITE (output_unit, '(A)') " In place 3D FFT (local) : fft3d_s"
498 0 : WRITE (output_unit, '(A,T60,3I7)') " Transform lengths ", n
499 0 : WRITE (output_unit, '(A,T60,3I7)') " Input/output array dimensions ", ld
500 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of input data ", in_sum
501 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of output data ", out_sum
502 : END IF
503 : END IF
504 :
505 678145 : CALL timestop(handle)
506 :
507 678145 : END SUBROUTINE fft3d_s
508 :
509 : ! **************************************************************************************************
510 : !> \brief ...
511 : !> \param fsign ...
512 : !> \param n ...
513 : !> \param cin ...
514 : !> \param gin ...
515 : !> \param rs_group ...
516 : !> \param yzp ...
517 : !> \param nyzray ...
518 : !> \param bo ...
519 : !> \param status ...
520 : !> \param debug ...
521 : ! **************************************************************************************************
522 3529842 : SUBROUTINE fft3d_ps(fsign, n, cin, gin, rs_group, yzp, nyzray, &
523 3529842 : bo, status, debug)
524 :
525 : INTEGER, INTENT(IN) :: fsign
526 : INTEGER, DIMENSION(:), INTENT(IN) :: n
527 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :, :), &
528 : INTENT(INOUT) :: cin
529 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
530 : INTENT(INOUT) :: gin
531 : TYPE(mp_cart_type), INTENT(IN) :: rs_group
532 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), &
533 : INTENT(IN) :: yzp
534 : INTEGER, CONTIGUOUS, DIMENSION(0:), INTENT(IN) :: nyzray
535 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:, :), &
536 : INTENT(IN) :: bo
537 : INTEGER, INTENT(OUT), OPTIONAL :: status
538 : LOGICAL, INTENT(IN), OPTIONAL :: debug
539 :
540 : CHARACTER(len=*), PARAMETER :: routineN = 'fft3d_ps'
541 :
542 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
543 3529842 : POINTER :: pbuf, qbuf, rbuf, sbuf
544 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :, :), &
545 3529842 : POINTER :: tbuf
546 : INTEGER :: g_pos, handle, lg, lmax, mcx2, mcz1, mcz2, mg, mmax, mx1, mx2, my1, mz2, n1, n2, &
547 : nmax, numtask, nx, ny, nz, output_unit, r_dim(2), r_pos(2), rp, sign, stat
548 3529842 : INTEGER, ALLOCATABLE, DIMENSION(:) :: p2p
549 : LOGICAL :: test
550 : REAL(KIND=dp) :: norm, sum_data
551 24708894 : TYPE(fft_scratch_sizes) :: fft_scratch_size
552 : TYPE(fft_scratch_type), POINTER :: fft_scratch
553 :
554 3529842 : CALL timeset(routineN, handle)
555 3529842 : output_unit = cp_logger_get_default_io_unit()
556 :
557 3529842 : IF (PRESENT(debug)) THEN
558 3529842 : test = debug
559 : ELSE
560 : test = .FALSE.
561 : END IF
562 :
563 3529842 : g_pos = rs_group%mepos
564 3529842 : numtask = rs_group%num_pe
565 10589526 : r_dim = rs_group%num_pe_cart
566 10589526 : r_pos = rs_group%mepos_cart
567 :
568 3529842 : IF (fsign == FWFFT) THEN
569 7086120 : norm = 1.0_dp/REAL(PRODUCT(n), KIND=dp)
570 1758312 : ELSE IF (fsign == BWFFT) THEN
571 1758312 : norm = 1.0_dp
572 : ELSE
573 0 : CPABORT("Unknown FFT direction!")
574 : END IF
575 :
576 3529842 : sign = fsign
577 :
578 3529842 : lg = SIZE(gin, 1)
579 3529842 : mg = SIZE(gin, 2)
580 :
581 3529842 : nx = SIZE(cin, 1)
582 3529842 : ny = SIZE(cin, 2)
583 3529842 : nz = SIZE(cin, 3)
584 :
585 3529842 : IF (mg == 0) THEN
586 : mmax = 1
587 : ELSE
588 3529842 : mmax = mg
589 : END IF
590 3529842 : lmax = MAX(lg, (nx*ny*nz)/mmax + 1)
591 :
592 10589526 : ALLOCATE (p2p(0:numtask - 1))
593 :
594 3529842 : CALL rs_group%rank_compare(rs_group, p2p)
595 :
596 3529842 : rp = p2p(g_pos)
597 3529842 : mx1 = bo(2, 1, rp, 1) - bo(1, 1, rp, 1) + 1
598 3529842 : my1 = bo(2, 2, rp, 1) - bo(1, 2, rp, 1) + 1
599 3529842 : mx2 = bo(2, 1, rp, 2) - bo(1, 1, rp, 2) + 1
600 3529842 : mz2 = bo(2, 3, rp, 2) - bo(1, 3, rp, 2) + 1
601 :
602 10589526 : n1 = MAXVAL(bo(2, 1, :, 1) - bo(1, 1, :, 1) + 1)
603 10589526 : n2 = MAXVAL(bo(2, 2, :, 1) - bo(1, 2, :, 1) + 1)
604 3529842 : nmax = MAX((2*n2)/numtask, 2)*mx2*mz2
605 10589526 : nmax = MAX(nmax, n1*MAXVAL(nyzray))
606 10589526 : n1 = MAXVAL(bo(2, 1, :, 2))
607 10589526 : n2 = MAXVAL(bo(2, 3, :, 2))
608 :
609 3529842 : fft_scratch_size%nx = nx
610 3529842 : fft_scratch_size%ny = ny
611 3529842 : fft_scratch_size%nz = nz
612 3529842 : fft_scratch_size%lmax = lmax
613 3529842 : fft_scratch_size%mmax = mmax
614 3529842 : fft_scratch_size%mx1 = mx1
615 3529842 : fft_scratch_size%mx2 = mx2
616 3529842 : fft_scratch_size%my1 = my1
617 3529842 : fft_scratch_size%mz2 = mz2
618 3529842 : fft_scratch_size%lg = lg
619 3529842 : fft_scratch_size%mg = mg
620 3529842 : fft_scratch_size%nbx = n1
621 3529842 : fft_scratch_size%nbz = n2
622 10589526 : mcz1 = MAXVAL(bo(2, 3, :, 1) - bo(1, 3, :, 1) + 1)
623 10589526 : mcx2 = MAXVAL(bo(2, 1, :, 2) - bo(1, 1, :, 2) + 1)
624 10589526 : mcz2 = MAXVAL(bo(2, 3, :, 2) - bo(1, 3, :, 2) + 1)
625 3529842 : fft_scratch_size%mcz1 = mcz1
626 3529842 : fft_scratch_size%mcx2 = mcx2
627 3529842 : fft_scratch_size%mcz2 = mcz2
628 3529842 : fft_scratch_size%nmax = nmax
629 10589526 : fft_scratch_size%nmray = MAXVAL(nyzray)
630 3529842 : fft_scratch_size%nyzray = nyzray(g_pos)
631 3529842 : fft_scratch_size%rs_group = rs_group
632 10589526 : fft_scratch_size%g_pos = g_pos
633 10589526 : fft_scratch_size%r_pos = r_pos
634 10589526 : fft_scratch_size%r_dim = r_dim
635 3529842 : fft_scratch_size%numtask = numtask
636 :
637 3529842 : IF (test) THEN
638 8 : IF (g_pos == 0 .AND. output_unit > 0) THEN
639 4 : WRITE (output_unit, '(A)') " Parallel 3D FFT : fft3d_ps"
640 4 : WRITE (output_unit, '(A,T60,3I7)') " Transform lengths ", n
641 4 : WRITE (output_unit, '(A,T67,2I7)') " Array dimensions (gin) ", lg, mg
642 4 : WRITE (output_unit, '(A,T60,3I7)') " Array dimensions (cin) ", nx, ny, nz
643 : END IF
644 : END IF
645 :
646 3529842 : IF (r_dim(2) > 1) THEN
647 :
648 : !
649 : ! real space is distributed over x and y coordinate
650 : ! we have two stages of communication
651 : !
652 :
653 0 : IF (r_dim(1) == 1) THEN
654 0 : CPABORT("This processor distribution is not supported.")
655 : END IF
656 0 : CALL get_fft_scratch(fft_scratch, tf_type=300, n=n, fft_sizes=fft_scratch_size)
657 :
658 0 : IF (sign == FWFFT) THEN
659 : ! cin -> gin
660 :
661 0 : IF (test) THEN
662 0 : sum_data = ABS(SUM(cin))
663 0 : CALL rs_group%sum(sum_data)
664 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
665 0 : WRITE (output_unit, '(A)') " Two step communication algorithm "
666 0 : WRITE (output_unit, '(A,T60,3I7)') " Transform Z ", n(3), mx1*my1
667 0 : WRITE (output_unit, '(A,T60,3I7)') " Transform Y ", n(2), mx2*mz2
668 0 : WRITE (output_unit, '(A,T67,2I7)') " Transform X ", n(1), nyzray(g_pos)
669 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(1) ", sum_data
670 : END IF
671 : END IF
672 :
673 0 : pbuf => fft_scratch%p1buf
674 0 : qbuf => fft_scratch%p2buf
675 :
676 : ! FFT along z
677 0 : CALL fft_1d(fft_scratch%fft_plan(1), cin, qbuf, norm, stat)
678 :
679 0 : rbuf => fft_scratch%p3buf
680 :
681 0 : IF (test) THEN
682 0 : sum_data = ABS(SUM(qbuf))
683 0 : CALL rs_group%sum(sum_data)
684 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
685 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(2) T", sum_data
686 : END IF
687 : END IF
688 :
689 : ! Exchange data ( transpose of matrix )
690 0 : CALL cube_transpose_2(qbuf, bo(:, :, :, 1), bo(:, :, :, 2), rbuf, fft_scratch)
691 :
692 0 : IF (test) THEN
693 0 : sum_data = ABS(SUM(rbuf))
694 0 : CALL rs_group%sum(sum_data)
695 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
696 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(3) T", sum_data
697 : END IF
698 : END IF
699 :
700 0 : pbuf => fft_scratch%p4buf
701 :
702 : ! FFT along y
703 0 : CALL fft_1d(fft_scratch%fft_plan(2), rbuf, pbuf, 1.0_dp, stat)
704 :
705 0 : qbuf => fft_scratch%p5buf
706 :
707 0 : IF (test) THEN
708 0 : sum_data = ABS(SUM(pbuf))
709 0 : CALL rs_group%sum(sum_data)
710 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
711 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(4) TS", sum_data
712 : END IF
713 : END IF
714 :
715 : ! Exchange data ( transpose of matrix ) and sort
716 : CALL xz_to_yz(pbuf, rs_group, r_dim, g_pos, p2p, yzp, nyzray, &
717 0 : bo(:, :, :, 2), qbuf, fft_scratch)
718 :
719 0 : IF (test) THEN
720 0 : sum_data = ABS(SUM(qbuf))
721 0 : CALL rs_group%sum(sum_data)
722 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
723 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(5) TS", sum_data
724 : END IF
725 : END IF
726 :
727 : ! FFT along x
728 0 : CALL fft_1d(fft_scratch%fft_plan(3), qbuf, gin, 1.0_dp, stat)
729 :
730 0 : IF (test) THEN
731 0 : sum_data = ABS(SUM(gin))
732 0 : CALL rs_group%sum(sum_data)
733 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
734 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(6) ", sum_data
735 : END IF
736 : END IF
737 :
738 0 : ELSE IF (sign == BWFFT) THEN
739 : ! gin -> cin
740 :
741 0 : IF (test) THEN
742 0 : sum_data = ABS(SUM(gin))
743 0 : CALL rs_group%sum(sum_data)
744 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
745 0 : WRITE (output_unit, '(A)') " Two step communication algorithm "
746 0 : WRITE (output_unit, '(A,T67,2I7)') " Transform X ", n(1), nyzray(g_pos)
747 0 : WRITE (output_unit, '(A,T60,3I7)') " Transform Y ", n(2), mx2*mz2
748 0 : WRITE (output_unit, '(A,T60,3I7)') " Transform Z ", n(3), mx1*my1
749 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(1) ", sum_data
750 : END IF
751 : END IF
752 :
753 0 : pbuf => fft_scratch%p7buf
754 :
755 : ! FFT along x
756 0 : CALL fft_1d(fft_scratch%fft_plan(4), gin, pbuf, norm, stat)
757 :
758 0 : qbuf => fft_scratch%p4buf
759 :
760 0 : IF (test) THEN
761 0 : sum_data = ABS(SUM(pbuf))
762 0 : CALL rs_group%sum(sum_data)
763 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
764 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(2) TS", sum_data
765 : END IF
766 : END IF
767 :
768 : ! Exchange data ( transpose of matrix ) and sort
769 : CALL yz_to_xz(pbuf, rs_group, r_dim, g_pos, p2p, yzp, nyzray, &
770 0 : bo(:, :, :, 2), qbuf, fft_scratch)
771 :
772 0 : IF (test) THEN
773 0 : sum_data = ABS(SUM(qbuf))
774 0 : CALL rs_group%sum(sum_data)
775 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
776 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(3) TS", sum_data
777 : END IF
778 : END IF
779 :
780 0 : rbuf => fft_scratch%p3buf
781 :
782 : ! FFT along y
783 0 : CALL fft_1d(fft_scratch%fft_plan(5), qbuf, rbuf, 1.0_dp, stat)
784 :
785 0 : pbuf => fft_scratch%p2buf
786 :
787 0 : IF (test) THEN
788 0 : sum_data = ABS(SUM(rbuf))
789 0 : CALL rs_group%sum(sum_data)
790 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
791 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(4) T", sum_data
792 : END IF
793 : END IF
794 :
795 : ! Exchange data ( transpose of matrix )
796 0 : CALL cube_transpose_1(rbuf, bo(:, :, :, 2), bo(:, :, :, 1), pbuf, fft_scratch)
797 :
798 0 : IF (test) THEN
799 0 : sum_data = ABS(SUM(pbuf))
800 0 : CALL rs_group%sum(sum_data)
801 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
802 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(5) T", sum_data
803 : END IF
804 : END IF
805 :
806 0 : qbuf => fft_scratch%p1buf
807 :
808 : ! FFT along z
809 0 : CALL fft_1d(fft_scratch%fft_plan(6), pbuf, cin, 1.0_dp, stat)
810 :
811 0 : IF (test) THEN
812 0 : sum_data = ABS(SUM(cin))
813 0 : CALL rs_group%sum(sum_data)
814 0 : IF (g_pos == 0 .AND. output_unit > 0) THEN
815 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(6) ", sum_data
816 : END IF
817 : END IF
818 :
819 : ELSE
820 :
821 0 : CPABORT("Illegal fsign parameter.")
822 :
823 : END IF
824 :
825 0 : CALL release_fft_scratch(fft_scratch)
826 :
827 : ELSE
828 :
829 : !
830 : ! real space is only distributed over x coordinate
831 : ! we have one stage of communication, after the transform of
832 : ! direction x
833 : !
834 :
835 3529842 : CALL get_fft_scratch(fft_scratch, tf_type=200, n=n, fft_sizes=fft_scratch_size)
836 :
837 3529842 : sbuf => fft_scratch%r1buf
838 3529842 : tbuf => fft_scratch%tbuf
839 :
840 3529842 : sbuf = z_zero
841 3529842 : tbuf = z_zero
842 :
843 3529842 : IF (sign == FWFFT) THEN
844 : ! cin -> gin
845 :
846 1771530 : IF (test) THEN
847 9284 : sum_data = ABS(SUM(cin))
848 4 : CALL rs_group%sum(sum_data)
849 4 : IF (g_pos == 0 .AND. output_unit > 0) THEN
850 2 : WRITE (output_unit, '(A)') " One step communication algorithm "
851 2 : WRITE (output_unit, '(A,T60,3I7)') " Transform YZ ", n(2), n(3), nx
852 2 : WRITE (output_unit, '(A,T67,2I7)') " Transform X ", n(1), nyzray(g_pos)
853 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(1) ", sum_data
854 : END IF
855 : END IF
856 :
857 : ! FFT along y and z
858 1771530 : CALL fft_1d(fft_scratch%fft_plan(1), cin, sbuf, 1._dp, stat)
859 1771530 : CALL fft_1d(fft_scratch%fft_plan(2), sbuf, tbuf, 1._dp, stat)
860 :
861 1771530 : IF (test) THEN
862 8740 : sum_data = ABS(SUM(tbuf))
863 4 : CALL rs_group%sum(sum_data)
864 4 : IF (g_pos == 0 .AND. output_unit > 0) THEN
865 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(2) TS", sum_data
866 : END IF
867 : END IF
868 :
869 : ! Exchange data ( transpose of matrix ) and sort
870 : CALL yz_to_x(tbuf, rs_group, g_pos, p2p, yzp, nyzray, &
871 1771530 : bo(:, :, :, 2), sbuf, fft_scratch)
872 :
873 1771530 : IF (test) THEN
874 8776 : sum_data = ABS(SUM(sbuf))
875 4 : CALL rs_group%sum(sum_data)
876 4 : IF (g_pos == 0 .AND. output_unit > 0) THEN
877 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(3) TS", sum_data
878 : END IF
879 : END IF
880 : ! FFT along x
881 1771530 : CALL fft_1d(fft_scratch%fft_plan(3), sbuf, gin, norm, stat)
882 :
883 1771530 : IF (test) THEN
884 8708 : sum_data = ABS(SUM(gin))
885 4 : CALL rs_group%sum(sum_data)
886 4 : IF (g_pos == 0 .AND. output_unit > 0) THEN
887 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(4) ", sum_data
888 : END IF
889 : END IF
890 :
891 1758312 : ELSE IF (sign == BWFFT) THEN
892 : ! gin -> cin
893 :
894 1758312 : IF (test) THEN
895 8708 : sum_data = ABS(SUM(gin))
896 4 : CALL rs_group%sum(sum_data)
897 4 : IF (g_pos == 0 .AND. output_unit > 0) THEN
898 2 : WRITE (output_unit, '(A)') " One step communication algorithm "
899 2 : WRITE (output_unit, '(A,T67,2I7)') " Transform X ", n(1), nyzray(g_pos)
900 2 : WRITE (output_unit, '(A,T60,3I7)') " Transform YZ ", n(2), n(3), nx
901 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(1) ", sum_data
902 : END IF
903 : END IF
904 :
905 : ! FFT along x
906 1758312 : CALL fft_1d(fft_scratch%fft_plan(4), gin, sbuf, norm, stat)
907 :
908 1758312 : IF (test) THEN
909 8776 : sum_data = ABS(SUM(sbuf))
910 4 : CALL rs_group%sum(sum_data)
911 4 : IF (g_pos == 0 .AND. output_unit > 0) THEN
912 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(2) TS", sum_data
913 : END IF
914 : END IF
915 :
916 : ! Exchange data ( transpose of matrix ) and sort
917 : CALL x_to_yz(sbuf, rs_group, g_pos, p2p, yzp, nyzray, &
918 1758312 : bo(:, :, :, 2), tbuf, fft_scratch)
919 :
920 1758312 : IF (test) THEN
921 8740 : sum_data = ABS(SUM(tbuf))
922 4 : CALL rs_group%sum(sum_data)
923 4 : IF (g_pos == 0 .AND. output_unit > 0) THEN
924 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(3) TS", sum_data
925 : END IF
926 : END IF
927 :
928 : ! FFT along y and z
929 1758312 : CALL fft_1d(fft_scratch%fft_plan(5), tbuf, sbuf, 1._dp, stat)
930 1758312 : CALL fft_1d(fft_scratch%fft_plan(6), sbuf, cin, 1._dp, stat)
931 :
932 1758312 : IF (test) THEN
933 9284 : sum_data = ABS(SUM(cin))
934 4 : CALL rs_group%sum(sum_data)
935 4 : IF (g_pos == 0 .AND. output_unit > 0) THEN
936 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(4) ", sum_data
937 : END IF
938 : END IF
939 : ELSE
940 0 : CPABORT("Illegal fsign parameter.")
941 : END IF
942 :
943 3529842 : CALL release_fft_scratch(fft_scratch)
944 :
945 : END IF
946 :
947 3529842 : DEALLOCATE (p2p)
948 :
949 3529842 : IF (PRESENT(status)) THEN
950 0 : status = stat
951 : END IF
952 3529842 : CALL timestop(handle)
953 :
954 7059684 : END SUBROUTINE fft3d_ps
955 :
956 : ! **************************************************************************************************
957 : !> \brief ...
958 : !> \param fsign ...
959 : !> \param n ...
960 : !> \param zin ...
961 : !> \param gin ...
962 : !> \param group ...
963 : !> \param bo ...
964 : !> \param status ...
965 : !> \param debug ...
966 : ! **************************************************************************************************
967 208 : SUBROUTINE fft3d_pb(fsign, n, zin, gin, group, bo, status, debug)
968 :
969 : INTEGER, INTENT(IN) :: fsign
970 : INTEGER, DIMENSION(3), INTENT(IN) :: n
971 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :, :), &
972 : INTENT(INOUT) :: zin
973 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
974 : INTENT(INOUT) :: gin
975 : TYPE(mp_cart_type), INTENT(IN) :: group
976 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:, :), &
977 : INTENT(IN) :: bo
978 : INTEGER, INTENT(OUT), OPTIONAL :: status
979 : LOGICAL, INTENT(IN), OPTIONAL :: debug
980 :
981 : CHARACTER(len=*), PARAMETER :: routineN = 'fft3d_pb'
982 :
983 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
984 208 : POINTER :: abuf, bbuf
985 : INTEGER :: handle, lg(2), lz(3), mcx2, mcy3, mcz1, &
986 : mcz2, mx1, mx2, mx3, my1, my2, my3, &
987 : my_pos, mz1, mz2, mz3, output_unit, &
988 : sign, stat
989 : INTEGER, DIMENSION(2) :: dim
990 : LOGICAL :: test
991 : REAL(KIND=dp) :: norm, sum_data
992 1456 : TYPE(fft_scratch_sizes) :: fft_scratch_size
993 : TYPE(fft_scratch_type), POINTER :: fft_scratch
994 :
995 : !------------------------------------------------------------------------------
996 : ! "Real Space" 1) xyZ or 1) xYZ
997 : ! 2) xYz or not used
998 : ! "G Space" 3) Xyz or 3) XYz
999 : !
1000 : ! There is one communicator (2-dimensional) for all distributions
1001 : ! np = n1 * n2, where np is the total number of processors
1002 : ! If n2 = 1, we have the second case and only one transpose step is needed
1003 : !
1004 : ! Assignment of dimensions to axis for different steps
1005 : ! First case: 1) n1=x; n2=y
1006 : ! 2) n1=x; n2=z
1007 : ! 3) n1=y; n2=z
1008 : ! Second case 1) n1=x
1009 : ! 3) n1=z
1010 : !
1011 : ! The more general case with two communicators for the initial and final
1012 : ! distribution is not covered.
1013 : !------------------------------------------------------------------------------
1014 :
1015 208 : CALL timeset(routineN, handle)
1016 208 : output_unit = cp_logger_get_default_io_unit()
1017 :
1018 624 : dim = group%num_pe_cart
1019 208 : my_pos = group%mepos
1020 :
1021 208 : IF (PRESENT(debug)) THEN
1022 208 : test = debug
1023 : ELSE
1024 : test = .FALSE.
1025 : END IF
1026 :
1027 208 : IF (fsign == FWFFT) THEN
1028 416 : norm = 1.0_dp/REAL(PRODUCT(n), KIND=dp)
1029 104 : ELSE IF (fsign == BWFFT) THEN
1030 104 : norm = 1.0_dp
1031 : ELSE
1032 0 : CPABORT("Unknown FFT direction!")
1033 : END IF
1034 :
1035 208 : sign = fsign
1036 :
1037 208 : IF (test) THEN
1038 8 : lg(1) = SIZE(gin, 1)
1039 8 : lg(2) = SIZE(gin, 2)
1040 8 : lz(1) = SIZE(zin, 1)
1041 8 : lz(2) = SIZE(zin, 2)
1042 8 : lz(3) = SIZE(zin, 3)
1043 8 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1044 4 : WRITE (output_unit, '(A)') " Parallel 3D FFT : fft3d_pb"
1045 4 : WRITE (output_unit, '(A,T60,3I7)') " Transform lengths ", n
1046 4 : WRITE (output_unit, '(A,T67,2I7)') " Array dimensions (gin) ", lg
1047 4 : WRITE (output_unit, '(A,T60,3I7)') " Array dimensions (cin) ", lz
1048 : END IF
1049 : END IF
1050 :
1051 208 : mx1 = bo(2, 1, my_pos, 1) - bo(1, 1, my_pos, 1) + 1
1052 208 : my1 = bo(2, 2, my_pos, 1) - bo(1, 2, my_pos, 1) + 1
1053 208 : mz1 = bo(2, 3, my_pos, 1) - bo(1, 3, my_pos, 1) + 1
1054 208 : mx2 = bo(2, 1, my_pos, 2) - bo(1, 1, my_pos, 2) + 1
1055 208 : my2 = bo(2, 2, my_pos, 2) - bo(1, 2, my_pos, 2) + 1
1056 208 : mz2 = bo(2, 3, my_pos, 2) - bo(1, 3, my_pos, 2) + 1
1057 208 : mx3 = bo(2, 1, my_pos, 3) - bo(1, 1, my_pos, 3) + 1
1058 208 : my3 = bo(2, 2, my_pos, 3) - bo(1, 2, my_pos, 3) + 1
1059 208 : mz3 = bo(2, 3, my_pos, 3) - bo(1, 3, my_pos, 3) + 1
1060 208 : fft_scratch_size%mx1 = mx1
1061 208 : fft_scratch_size%mx2 = mx2
1062 208 : fft_scratch_size%mx3 = mx3
1063 208 : fft_scratch_size%my1 = my1
1064 208 : fft_scratch_size%my2 = my2
1065 208 : fft_scratch_size%my3 = my3
1066 208 : fft_scratch_size%mz1 = mz1
1067 208 : fft_scratch_size%mz2 = mz2
1068 208 : fft_scratch_size%mz3 = mz3
1069 624 : mcz1 = MAXVAL(bo(2, 3, :, 1) - bo(1, 3, :, 1) + 1)
1070 624 : mcx2 = MAXVAL(bo(2, 1, :, 2) - bo(1, 1, :, 2) + 1)
1071 624 : mcz2 = MAXVAL(bo(2, 3, :, 2) - bo(1, 3, :, 2) + 1)
1072 624 : mcy3 = MAXVAL(bo(2, 2, :, 3) - bo(1, 2, :, 3) + 1)
1073 208 : fft_scratch_size%mcz1 = mcz1
1074 208 : fft_scratch_size%mcx2 = mcx2
1075 208 : fft_scratch_size%mcz2 = mcz2
1076 208 : fft_scratch_size%mcy3 = mcy3
1077 208 : fft_scratch_size%rs_group = group
1078 624 : fft_scratch_size%g_pos = my_pos
1079 208 : fft_scratch_size%numtask = DIM(1)*DIM(2)
1080 :
1081 208 : IF (DIM(1) > 1 .AND. DIM(2) > 1) THEN
1082 :
1083 : !
1084 : ! First case; two stages of communication
1085 : !
1086 :
1087 0 : CALL get_fft_scratch(fft_scratch, tf_type=100, n=n, fft_sizes=fft_scratch_size)
1088 :
1089 0 : IF (sign == FWFFT) THEN
1090 : ! Stage 1 -> 3
1091 :
1092 0 : bbuf => fft_scratch%a2buf
1093 :
1094 0 : IF (test) THEN
1095 0 : sum_data = ABS(SUM(zin))
1096 0 : CALL group%sum(sum_data)
1097 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1098 0 : WRITE (output_unit, '(A)') " Two step communication algorithm "
1099 0 : WRITE (output_unit, '(A,T67,2I7)') " Transform Z ", n(3), mx1*my1
1100 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(1) ", sum_data
1101 : END IF
1102 : END IF
1103 :
1104 : ! FFT along z
1105 0 : CALL fft_1d(fft_scratch%fft_plan(1), zin, bbuf, norm, stat)
1106 :
1107 0 : abuf => fft_scratch%a3buf
1108 :
1109 0 : IF (test) THEN
1110 0 : sum_data = ABS(SUM(bbuf))
1111 0 : CALL group%sum(sum_data)
1112 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1113 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(2) T", sum_data
1114 : END IF
1115 : END IF
1116 :
1117 0 : CALL cube_transpose_2(bbuf, bo(:, :, :, 1), bo(:, :, :, 2), abuf, fft_scratch)
1118 :
1119 0 : bbuf => fft_scratch%a4buf
1120 :
1121 0 : IF (test) THEN
1122 0 : sum_data = ABS(SUM(abuf))
1123 0 : CALL group%sum(sum_data)
1124 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1125 0 : WRITE (output_unit, '(A,T67,2I7)') " Transform Y ", n(2), mx2*mz2
1126 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(3) ", sum_data
1127 : END IF
1128 : END IF
1129 :
1130 : ! FFT along y
1131 0 : CALL fft_1d(fft_scratch%fft_plan(2), abuf, bbuf, 1.0_dp, stat)
1132 :
1133 0 : abuf => fft_scratch%a5buf
1134 :
1135 0 : IF (test) THEN
1136 0 : sum_data = ABS(SUM(bbuf))
1137 0 : CALL group%sum(sum_data)
1138 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1139 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(4) T", sum_data
1140 : END IF
1141 : END IF
1142 :
1143 0 : CALL cube_transpose_4(bbuf, bo(:, :, :, 2), bo(:, :, :, 3), abuf, fft_scratch)
1144 :
1145 0 : IF (test) THEN
1146 0 : sum_data = ABS(SUM(abuf))
1147 0 : CALL group%sum(sum_data)
1148 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1149 0 : WRITE (output_unit, '(A,T67,2I7)') " Transform X ", n(1), my3*mz3
1150 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(5) ", sum_data
1151 : END IF
1152 : END IF
1153 :
1154 : ! FFT along x
1155 0 : CALL fft_1d(fft_scratch%fft_plan(3), abuf, gin, 1.0_dp, stat)
1156 :
1157 0 : IF (test) THEN
1158 0 : sum_data = ABS(SUM(gin))
1159 0 : CALL group%sum(sum_data)
1160 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1161 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(6) ", sum_data
1162 : END IF
1163 : END IF
1164 :
1165 0 : ELSE IF (sign == BWFFT) THEN
1166 : ! Stage 3 -> 1
1167 :
1168 0 : bbuf => fft_scratch%a5buf
1169 :
1170 0 : IF (test) THEN
1171 0 : sum_data = ABS(SUM(gin))
1172 0 : CALL group%sum(sum_data)
1173 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1174 0 : WRITE (output_unit, '(A)') " Two step communication algorithm "
1175 0 : WRITE (output_unit, '(A,T67,2I7)') " Transform X ", n(1), my3*mz3
1176 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(1) ", sum_data
1177 : END IF
1178 : END IF
1179 :
1180 : ! FFT along x
1181 0 : CALL fft_1d(fft_scratch%fft_plan(4), gin, bbuf, 1.0_dp, stat)
1182 :
1183 0 : abuf => fft_scratch%a4buf
1184 :
1185 0 : IF (test) THEN
1186 0 : sum_data = ABS(SUM(bbuf))
1187 0 : CALL group%sum(sum_data)
1188 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1189 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(2) T", sum_data
1190 : END IF
1191 : END IF
1192 :
1193 0 : CALL cube_transpose_3(bbuf, bo(:, :, :, 3), bo(:, :, :, 2), abuf, fft_scratch)
1194 :
1195 0 : bbuf => fft_scratch%a3buf
1196 :
1197 0 : IF (test) THEN
1198 0 : sum_data = ABS(SUM(abuf))
1199 0 : CALL group%sum(sum_data)
1200 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1201 0 : WRITE (output_unit, '(A,T67,2I7)') " Transform Y ", n(2), mx2*mz2
1202 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(3) ", sum_data
1203 : END IF
1204 : END IF
1205 :
1206 : ! FFT along y
1207 0 : CALL fft_1d(fft_scratch%fft_plan(5), abuf, bbuf, 1.0_dp, stat)
1208 :
1209 0 : abuf => fft_scratch%a2buf
1210 :
1211 0 : IF (test) THEN
1212 0 : sum_data = ABS(SUM(bbuf))
1213 0 : CALL group%sum(sum_data)
1214 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1215 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(4) T", sum_data
1216 : END IF
1217 : END IF
1218 :
1219 0 : CALL cube_transpose_1(bbuf, bo(:, :, :, 2), bo(:, :, :, 1), abuf, fft_scratch)
1220 :
1221 0 : IF (test) THEN
1222 0 : sum_data = ABS(SUM(abuf))
1223 0 : CALL group%sum(sum_data)
1224 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1225 0 : WRITE (output_unit, '(A,T67,2I7)') " Transform Z ", n(3), mx1*my1
1226 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(5) ", sum_data
1227 : END IF
1228 : END IF
1229 :
1230 : ! FFT along z
1231 0 : CALL fft_1d(fft_scratch%fft_plan(6), abuf, zin, norm, stat)
1232 :
1233 0 : IF (test) THEN
1234 0 : sum_data = ABS(SUM(zin))
1235 0 : CALL group%sum(sum_data)
1236 0 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1237 0 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(6) ", sum_data
1238 : END IF
1239 : END IF
1240 :
1241 : ELSE
1242 0 : CPABORT("Illegal fsign parameter.")
1243 : END IF
1244 :
1245 0 : CALL release_fft_scratch(fft_scratch)
1246 :
1247 208 : ELSE IF (DIM(2) == 1) THEN
1248 :
1249 : !
1250 : ! Second case; one stage of communication
1251 : !
1252 :
1253 208 : CALL get_fft_scratch(fft_scratch, tf_type=101, n=n, fft_sizes=fft_scratch_size)
1254 :
1255 208 : IF (sign == FWFFT) THEN
1256 : ! Stage 1 -> 3
1257 :
1258 104 : IF (test) THEN
1259 9284 : sum_data = ABS(SUM(zin))
1260 4 : CALL group%sum(sum_data)
1261 4 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1262 2 : WRITE (output_unit, '(A)') " one step communication algorithm "
1263 2 : WRITE (output_unit, '(A,T67,2I7)') " Transform Z ", n(3), mx1*my1
1264 2 : WRITE (output_unit, '(A,T67,2I7)') " Transform Y ", n(2), mx1*mz1
1265 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(1) ", sum_data
1266 : END IF
1267 : END IF
1268 :
1269 104 : abuf => fft_scratch%a3buf
1270 104 : bbuf => fft_scratch%a4buf
1271 : ! FFT along z and y
1272 104 : CALL fft_1d(fft_scratch%fft_plan(1), zin, abuf, norm, stat)
1273 104 : CALL fft_1d(fft_scratch%fft_plan(2), abuf, bbuf, 1.0_dp, stat)
1274 :
1275 104 : abuf => fft_scratch%a5buf
1276 :
1277 104 : IF (test) THEN
1278 8708 : sum_data = ABS(SUM(bbuf))
1279 4 : CALL group%sum(sum_data)
1280 4 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1281 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(2) T", sum_data
1282 : END IF
1283 : END IF
1284 :
1285 104 : CALL cube_transpose_6(bbuf, group, bo(:, :, :, 1), bo(:, :, :, 3), abuf, fft_scratch)
1286 :
1287 104 : IF (test) THEN
1288 8260 : sum_data = ABS(SUM(abuf))
1289 4 : CALL group%sum(sum_data)
1290 4 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1291 2 : WRITE (output_unit, '(A,T67,2I7)') " Transform X ", n(1), my3*mz3
1292 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(3) ", sum_data
1293 : END IF
1294 : END IF
1295 :
1296 : ! FFT along x
1297 104 : CALL fft_1d(fft_scratch%fft_plan(3), abuf, gin, 1.0_dp, stat)
1298 :
1299 104 : IF (test) THEN
1300 8708 : sum_data = ABS(SUM(gin))
1301 4 : CALL group%sum(sum_data)
1302 4 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1303 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(4) ", sum_data
1304 : END IF
1305 : END IF
1306 :
1307 104 : ELSE IF (sign == BWFFT) THEN
1308 : ! Stage 3 -> 1
1309 :
1310 104 : IF (test) THEN
1311 8708 : sum_data = ABS(SUM(gin))
1312 4 : CALL group%sum(sum_data)
1313 4 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1314 2 : WRITE (output_unit, '(A)') " one step communication algorithm "
1315 2 : WRITE (output_unit, '(A,T67,2I7)') " Transform X ", n(1), my3*mz3
1316 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(1) ", sum_data
1317 : END IF
1318 : END IF
1319 :
1320 104 : bbuf => fft_scratch%a5buf
1321 :
1322 : ! FFT along x
1323 104 : CALL fft_1d(fft_scratch%fft_plan(4), gin, bbuf, 1.0_dp, stat)
1324 :
1325 104 : abuf => fft_scratch%a4buf
1326 :
1327 104 : IF (test) THEN
1328 8260 : sum_data = ABS(SUM(bbuf))
1329 4 : CALL group%sum(sum_data)
1330 4 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1331 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(2) T", sum_data
1332 : END IF
1333 : END IF
1334 :
1335 104 : CALL cube_transpose_5(bbuf, group, bo(:, :, :, 3), bo(:, :, :, 1), abuf, fft_scratch)
1336 :
1337 104 : bbuf => fft_scratch%a3buf
1338 :
1339 104 : IF (test) THEN
1340 8708 : sum_data = ABS(SUM(abuf))
1341 4 : CALL group%sum(sum_data)
1342 4 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1343 2 : WRITE (output_unit, '(A,T67,2I7)') " Transform Y ", n(2), mx1*mz1
1344 2 : WRITE (output_unit, '(A,T67,2I7)') " Transform Z ", n(3), mx1*my1
1345 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(3) ", sum_data
1346 : END IF
1347 : END IF
1348 :
1349 : ! FFT along y
1350 104 : CALL fft_1d(fft_scratch%fft_plan(5), abuf, bbuf, 1.0_dp, stat)
1351 :
1352 : ! FFT along z
1353 104 : CALL fft_1d(fft_scratch%fft_plan(6), bbuf, zin, norm, stat)
1354 :
1355 104 : IF (test) THEN
1356 9284 : sum_data = ABS(SUM(zin))
1357 4 : CALL group%sum(sum_data)
1358 4 : IF (my_pos == 0 .AND. output_unit > 0) THEN
1359 2 : WRITE (output_unit, '(A,T61,E20.14)') " Sum of data(4) ", sum_data
1360 : END IF
1361 : END IF
1362 :
1363 : ELSE
1364 0 : CPABORT("Illegal fsign parameter.")
1365 : END IF
1366 :
1367 208 : CALL release_fft_scratch(fft_scratch)
1368 :
1369 : ELSE
1370 :
1371 0 : CPABORT("Partition not implemented.")
1372 :
1373 : END IF
1374 :
1375 208 : IF (PRESENT(status)) THEN
1376 0 : status = stat
1377 : END IF
1378 :
1379 208 : CALL timestop(handle)
1380 :
1381 416 : END SUBROUTINE fft3d_pb
1382 :
1383 : ! **************************************************************************************************
1384 : !> \brief ...
1385 : !> \param sb ...
1386 : !> \param group ...
1387 : !> \param my_pos ...
1388 : !> \param p2p ...
1389 : !> \param yzp ...
1390 : !> \param nray ...
1391 : !> \param bo ...
1392 : !> \param tb ...
1393 : !> \param fft_scratch ...
1394 : !> \par History
1395 : !> 15. Feb. 2006 : single precision all_to_all
1396 : !> \author JGH (14-Jan-2001)
1397 : ! **************************************************************************************************
1398 1758312 : SUBROUTINE x_to_yz(sb, group, my_pos, p2p, yzp, nray, bo, tb, fft_scratch)
1399 :
1400 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
1401 : INTENT(IN) :: sb
1402 :
1403 : CLASS(mp_comm_type), INTENT(IN) :: group
1404 : INTEGER, INTENT(IN) :: my_pos
1405 : INTEGER, CONTIGUOUS, DIMENSION(0:), INTENT(IN) :: p2p
1406 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), &
1407 : INTENT(IN) :: yzp
1408 : INTEGER, CONTIGUOUS, DIMENSION(0:), INTENT(IN) :: nray
1409 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), &
1410 : INTENT(IN) :: bo
1411 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :, :), &
1412 : INTENT(INOUT) :: tb
1413 : TYPE(fft_scratch_type), INTENT(IN) :: fft_scratch
1414 :
1415 : CHARACTER(len=*), PARAMETER :: routineN = 'x_to_yz'
1416 :
1417 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
1418 1758312 : POINTER :: rr
1419 : COMPLEX(KIND=sp), CONTIGUOUS, DIMENSION(:, :), &
1420 1758312 : POINTER :: ss, tt
1421 : INTEGER :: handle, ip, ir, ix, ixx, iy, iz, mpr, &
1422 : nm, np, nr, nx
1423 1758312 : INTEGER, CONTIGUOUS, DIMENSION(:), POINTER :: rcount, rdispl, scount, sdispl
1424 :
1425 1758312 : CALL timeset(routineN, handle)
1426 :
1427 1758312 : np = SIZE(p2p)
1428 1758312 : scount => fft_scratch%scount
1429 1758312 : rcount => fft_scratch%rcount
1430 1758312 : sdispl => fft_scratch%sdispl
1431 1758312 : rdispl => fft_scratch%rdispl
1432 :
1433 1758312 : IF (alltoall_sgl) THEN
1434 230 : ss => fft_scratch%ss
1435 230 : tt => fft_scratch%tt
1436 3441099 : ss(:, :) = CMPLX(sb(:, :), KIND=sp)
1437 230 : tt(:, :) = 0._sp
1438 : ELSE
1439 1758082 : rr => fft_scratch%rr
1440 : END IF
1441 :
1442 1758312 : mpr = p2p(my_pos)
1443 5274936 : nm = MAXVAL(nray(0:np - 1))
1444 1758312 : nr = nray(my_pos)
1445 : !$OMP PARALLEL DO DEFAULT(NONE), &
1446 : !$OMP PRIVATE(ix,nx), &
1447 1758312 : !$OMP SHARED(np,p2p,bo,nr,scount,sdispl)
1448 : DO ip = 0, np - 1
1449 : ix = p2p(ip)
1450 : nx = bo(2, 1, ix) - bo(1, 1, ix) + 1
1451 : scount(ip) = nr*nx
1452 : sdispl(ip) = nr*(bo(1, 1, ix) - 1)
1453 : END DO
1454 : !$OMP END PARALLEL DO
1455 1758312 : nx = bo(2, 1, mpr) - bo(1, 1, mpr) + 1
1456 : !$OMP PARALLEL DO DEFAULT(NONE), &
1457 : !$OMP PRIVATE(nr), &
1458 1758312 : !$OMP SHARED(np,nray,nx,rcount,rdispl,nm)
1459 : DO ip = 0, np - 1
1460 : nr = nray(ip)
1461 : rcount(ip) = nr*nx
1462 : rdispl(ip) = nm*nx*ip
1463 : END DO
1464 : !$OMP END PARALLEL DO
1465 1758312 : IF (alltoall_sgl) THEN
1466 230 : CALL group%alltoall(ss, scount, sdispl, tt, rcount, rdispl)
1467 : ELSE
1468 1758082 : CALL group%alltoall(sb, scount, sdispl, rr, rcount, rdispl)
1469 : END IF
1470 :
1471 1758312 : nx = bo(2, 1, mpr) - bo(1, 1, mpr) + 1
1472 : !$OMP PARALLEL DO DEFAULT(NONE) COLLAPSE(2) &
1473 : !$OMP PRIVATE(ixx,ir,iy,iz,ix) &
1474 1758312 : !$OMP SHARED(np,nray,nx,alltoall_sgl,yzp,tt,rr,tb)
1475 : DO ip = 0, np - 1
1476 : DO ix = 1, nx
1477 : ixx = nray(ip)*(ix - 1)
1478 : IF (alltoall_sgl) THEN
1479 : DO ir = 1, nray(ip)
1480 : iy = yzp(1, ir, ip)
1481 : iz = yzp(2, ir, ip)
1482 : tb(iy, iz, ix) = tt(ir + ixx, ip)
1483 : END DO
1484 : ELSE
1485 : DO ir = 1, nray(ip)
1486 : iy = yzp(1, ir, ip)
1487 : iz = yzp(2, ir, ip)
1488 : tb(iy, iz, ix) = rr(ir + ixx, ip)
1489 : END DO
1490 : END IF
1491 : END DO
1492 : END DO
1493 : !$OMP END PARALLEL DO
1494 :
1495 1758312 : CALL timestop(handle)
1496 :
1497 1758312 : END SUBROUTINE x_to_yz
1498 :
1499 : ! **************************************************************************************************
1500 : !> \brief ...
1501 : !> \param tb ...
1502 : !> \param group ...
1503 : !> \param my_pos ...
1504 : !> \param p2p ...
1505 : !> \param yzp ...
1506 : !> \param nray ...
1507 : !> \param bo ...
1508 : !> \param sb ...
1509 : !> \param fft_scratch ...
1510 : !> \par History
1511 : !> 15. Feb. 2006 : single precision all_to_all
1512 : !> \author JGH (14-Jan-2001)
1513 : ! **************************************************************************************************
1514 1771530 : SUBROUTINE yz_to_x(tb, group, my_pos, p2p, yzp, nray, bo, sb, fft_scratch)
1515 :
1516 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :, :), &
1517 : INTENT(IN) :: tb
1518 :
1519 : CLASS(mp_comm_type), INTENT(IN) :: group
1520 : INTEGER, INTENT(IN) :: my_pos
1521 : INTEGER, CONTIGUOUS, DIMENSION(0:), INTENT(IN) :: p2p
1522 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), &
1523 : INTENT(IN) :: yzp
1524 : INTEGER, CONTIGUOUS, DIMENSION(0:), INTENT(IN) :: nray
1525 : INTEGER, DIMENSION(:, :, 0:), INTENT(IN) :: bo
1526 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
1527 : INTENT(INOUT) :: sb
1528 : TYPE(fft_scratch_type), INTENT(IN) :: fft_scratch
1529 :
1530 : CHARACTER(len=*), PARAMETER :: routineN = 'yz_to_x'
1531 :
1532 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
1533 1771530 : POINTER :: rr
1534 : COMPLEX(KIND=sp), CONTIGUOUS, DIMENSION(:, :), &
1535 1771530 : POINTER :: ss, tt
1536 : INTEGER :: handle, ip, ir, ix, ixx, iy, iz, mpr, &
1537 : nm, np, nr, nx
1538 1771530 : INTEGER, CONTIGUOUS, DIMENSION(:), POINTER :: rcount, rdispl, scount, sdispl
1539 :
1540 1771530 : CALL timeset(routineN, handle)
1541 :
1542 1771530 : np = SIZE(p2p)
1543 1771530 : mpr = p2p(my_pos)
1544 1771530 : scount => fft_scratch%scount
1545 1771530 : rcount => fft_scratch%rcount
1546 1771530 : sdispl => fft_scratch%sdispl
1547 1771530 : rdispl => fft_scratch%rdispl
1548 :
1549 1771530 : IF (alltoall_sgl) THEN
1550 238 : ss => fft_scratch%ss
1551 238 : tt => fft_scratch%tt
1552 238 : ss = 0._sp
1553 238 : tt = 0._sp
1554 : ELSE
1555 1771292 : rr => fft_scratch%rr
1556 : END IF
1557 :
1558 1771530 : nx = bo(2, 1, mpr) - bo(1, 1, mpr) + 1
1559 : !$OMP PARALLEL DO DEFAULT(NONE) COLLAPSE(2) &
1560 : !$OMP PRIVATE(ip, ixx, ir, iy, iz, ix) &
1561 1771530 : !$OMP SHARED(np,nray,nx,alltoall_sgl,yzp,tb,tt,rr)
1562 : DO ip = 0, np - 1
1563 : DO ix = 1, nx
1564 : ixx = nray(ip)*(ix - 1)
1565 : IF (alltoall_sgl) THEN
1566 : DO ir = 1, nray(ip)
1567 : iy = yzp(1, ir, ip)
1568 : iz = yzp(2, ir, ip)
1569 : tt(ir + ixx, ip) = CMPLX(tb(iy, iz, ix), KIND=sp)
1570 : END DO
1571 : ELSE
1572 : DO ir = 1, nray(ip)
1573 : iy = yzp(1, ir, ip)
1574 : iz = yzp(2, ir, ip)
1575 : rr(ir + ixx, ip) = tb(iy, iz, ix)
1576 : END DO
1577 : END IF
1578 : END DO
1579 : END DO
1580 : !$OMP END PARALLEL DO
1581 5314590 : nm = MAXVAL(nray(0:np - 1))
1582 1771530 : nr = nray(my_pos)
1583 : !$OMP PARALLEL DO DEFAULT(NONE), &
1584 : !$OMP PRIVATE(ix,nx), &
1585 1771530 : !$OMP SHARED(np,p2p,bo,rcount,rdispl,nr)
1586 : DO ip = 0, np - 1
1587 : ix = p2p(ip)
1588 : nx = bo(2, 1, ix) - bo(1, 1, ix) + 1
1589 : rcount(ip) = nr*nx
1590 : rdispl(ip) = nr*(bo(1, 1, ix) - 1)
1591 : END DO
1592 : !$OMP END PARALLEL DO
1593 1771530 : nx = bo(2, 1, mpr) - bo(1, 1, mpr) + 1
1594 : !$OMP PARALLEL DO DEFAULT(NONE), &
1595 : !$OMP PRIVATE(nr), &
1596 1771530 : !$OMP SHARED(np,nray,scount,sdispl,nx,nm)
1597 : DO ip = 0, np - 1
1598 : nr = nray(ip)
1599 : scount(ip) = nr*nx
1600 : sdispl(ip) = nm*nx*ip
1601 : END DO
1602 : !$OMP END PARALLEL DO
1603 :
1604 1771530 : IF (alltoall_sgl) THEN
1605 238 : CALL group%alltoall(tt, scount, sdispl, ss, rcount, rdispl)
1606 3703835 : sb = ss
1607 : ELSE
1608 1771292 : CALL group%alltoall(rr, scount, sdispl, sb, rcount, rdispl)
1609 : END IF
1610 :
1611 1771530 : CALL timestop(handle)
1612 :
1613 1771530 : END SUBROUTINE yz_to_x
1614 :
1615 : ! **************************************************************************************************
1616 : !> \brief ...
1617 : !> \param sb ...
1618 : !> \param group ...
1619 : !> \param dims ...
1620 : !> \param my_pos ...
1621 : !> \param p2p ...
1622 : !> \param yzp ...
1623 : !> \param nray ...
1624 : !> \param bo ...
1625 : !> \param tb ...
1626 : !> \param fft_scratch ...
1627 : !> \par History
1628 : !> 15. Feb. 2006 : single precision all_to_all
1629 : !> \author JGH (18-Jan-2001)
1630 : ! **************************************************************************************************
1631 0 : SUBROUTINE yz_to_xz(sb, group, dims, my_pos, p2p, yzp, nray, bo, tb, fft_scratch)
1632 :
1633 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
1634 : INTENT(IN) :: sb
1635 :
1636 : CLASS(mp_comm_type), INTENT(IN) :: group
1637 : INTEGER, DIMENSION(2), INTENT(IN) :: dims
1638 : INTEGER, INTENT(IN) :: my_pos
1639 : INTEGER, CONTIGUOUS, DIMENSION(0:), INTENT(IN) :: p2p
1640 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), INTENT(IN) :: yzp
1641 : INTEGER, CONTIGUOUS, DIMENSION(0:), INTENT(IN) :: nray
1642 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), INTENT(IN) :: bo
1643 : COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(INOUT), CONTIGUOUS :: tb
1644 : TYPE(fft_scratch_type), INTENT(INOUT) :: fft_scratch
1645 :
1646 : CHARACTER(len=*), PARAMETER :: routineN = 'yz_to_xz'
1647 :
1648 0 : COMPLEX(KIND=dp), DIMENSION(:), POINTER, CONTIGUOUS :: xzbuf, yzbuf
1649 0 : COMPLEX(KIND=sp), DIMENSION(:), POINTER, CONTIGUOUS :: xzbuf_sgl, yzbuf_sgl
1650 : INTEGER :: handle, icrs, ip, ipl, ipr, ir, ix, iz, &
1651 : jj, jx, jy, jz, myx, myz, np, npx, &
1652 : npz, nx, nz, rs_pos
1653 0 : INTEGER, DIMENSION(:), POINTER, CONTIGUOUS :: pzcoord, rcount, rdispl, scount, sdispl, &
1654 0 : xcor, zcor
1655 0 : INTEGER, DIMENSION(:, :), CONTIGUOUS, POINTER :: pgrid
1656 :
1657 0 : CALL timeset(routineN, handle)
1658 :
1659 0 : np = SIZE(p2p)
1660 :
1661 0 : rs_pos = p2p(my_pos)
1662 :
1663 0 : IF (alltoall_sgl) THEN
1664 0 : yzbuf_sgl => fft_scratch%yzbuf_sgl
1665 0 : xzbuf_sgl => fft_scratch%xzbuf_sgl
1666 : ELSE
1667 0 : yzbuf => fft_scratch%yzbuf
1668 0 : xzbuf => fft_scratch%xzbuf
1669 : END IF
1670 0 : npx = dims(1)
1671 0 : npz = dims(2)
1672 0 : pgrid => fft_scratch%pgrid
1673 0 : xcor => fft_scratch%xcor
1674 0 : zcor => fft_scratch%zcor
1675 0 : pzcoord => fft_scratch%pzcoord
1676 0 : scount => fft_scratch%scount
1677 0 : rcount => fft_scratch%rcount
1678 0 : sdispl => fft_scratch%sdispl
1679 0 : rdispl => fft_scratch%rdispl
1680 :
1681 0 : nx = SIZE(sb, 2)
1682 :
1683 : ! If the send and recv counts are not already cached, then
1684 : ! calculate and store them
1685 0 : IF (fft_scratch%in == 0) THEN
1686 :
1687 0 : scount = 0
1688 :
1689 0 : DO ix = 0, npx - 1
1690 0 : ip = pgrid(ix, 0)
1691 0 : xcor(bo(1, 1, ip):bo(2, 1, ip)) = ix
1692 : END DO
1693 0 : DO iz = 0, npz - 1
1694 0 : ip = pgrid(0, iz)
1695 0 : zcor(bo(1, 3, ip):bo(2, 3, ip)) = iz
1696 : END DO
1697 0 : DO jx = 1, nx
1698 0 : IF (alltoall_sgl) THEN
1699 0 : DO ir = 1, nray(my_pos)
1700 0 : jy = yzp(1, ir, my_pos)
1701 0 : jz = yzp(2, ir, my_pos)
1702 0 : ip = pgrid(xcor(jx), zcor(jz))
1703 0 : scount(ip) = scount(ip) + 1
1704 : END DO
1705 : ELSE
1706 0 : DO ir = 1, nray(my_pos)
1707 0 : jy = yzp(1, ir, my_pos)
1708 0 : jz = yzp(2, ir, my_pos)
1709 0 : ip = pgrid(xcor(jx), zcor(jz))
1710 0 : scount(ip) = scount(ip) + 1
1711 : END DO
1712 : END IF
1713 : END DO
1714 :
1715 0 : CALL group%alltoall(scount, rcount, 1)
1716 0 : fft_scratch%yzcount = scount
1717 0 : fft_scratch%xzcount = rcount
1718 :
1719 : ! Work out the correct displacements in the buffers
1720 0 : sdispl(0) = 0
1721 0 : rdispl(0) = 0
1722 0 : DO ip = 1, np - 1
1723 0 : sdispl(ip) = sdispl(ip - 1) + scount(ip - 1)
1724 0 : rdispl(ip) = rdispl(ip - 1) + rcount(ip - 1)
1725 : END DO
1726 :
1727 0 : fft_scratch%yzdispl = sdispl
1728 0 : fft_scratch%xzdispl = rdispl
1729 :
1730 0 : icrs = 0
1731 0 : DO ip = 0, np - 1
1732 0 : IF (scount(ip) /= 0) icrs = icrs + 1
1733 0 : IF (rcount(ip) /= 0) icrs = icrs + 1
1734 : END DO
1735 0 : CALL group%sum(icrs)
1736 0 : fft_scratch%rsratio = REAL(icrs, KIND=dp)/(REAL(2*np, KIND=dp)*REAL(np, KIND=dp))
1737 :
1738 0 : fft_scratch%in = 1
1739 : ELSE
1740 0 : scount = fft_scratch%yzcount
1741 0 : rcount = fft_scratch%xzcount
1742 0 : sdispl = fft_scratch%yzdispl
1743 0 : rdispl = fft_scratch%xzdispl
1744 : END IF
1745 :
1746 : ! Do the actual packing
1747 : !$OMP PARALLEL DO DEFAULT(NONE), &
1748 : !$OMP PRIVATE(ipl,jj,nx,ir,jx,jy,jz),&
1749 : !$OMP SHARED(np,p2p,pzcoord,bo,nray,yzp,zcor),&
1750 : !$OMP SHARED(yzbuf,sb,scount,sdispl,my_pos),&
1751 0 : !$OMP SHARED(yzbuf_sgl,alltoall_sgl)
1752 : DO ip = 0, np - 1
1753 : IF (scount(ip) == 0) CYCLE
1754 : ipl = p2p(ip)
1755 : jj = 0
1756 : nx = bo(2, 1, ipl) - bo(1, 1, ipl) + 1
1757 : DO ir = 1, nray(my_pos)
1758 : jz = yzp(2, ir, my_pos)
1759 : IF (zcor(jz) == pzcoord(ipl)) THEN
1760 : jj = jj + 1
1761 : jy = yzp(1, ir, my_pos)
1762 : IF (alltoall_sgl) THEN
1763 : DO jx = 0, nx - 1
1764 : yzbuf_sgl(sdispl(ip) + jj + jx*scount(ip)/nx) = CMPLX(sb(ir, jx + bo(1, 1, ipl)), KIND=sp)
1765 : END DO
1766 : ELSE
1767 : DO jx = 0, nx - 1
1768 : yzbuf(sdispl(ip) + jj + jx*scount(ip)/nx) = sb(ir, jx + bo(1, 1, ipl))
1769 : END DO
1770 : END IF
1771 : END IF
1772 : END DO
1773 : END DO
1774 : !$OMP END PARALLEL DO
1775 :
1776 0 : IF (alltoall_sgl) THEN
1777 0 : CALL group%alltoall(yzbuf_sgl, scount, sdispl, xzbuf_sgl, rcount, rdispl)
1778 : ELSE
1779 0 : IF (fft_scratch%rsratio < ratio_sparse_alltoall) THEN
1780 0 : CALL sparse_alltoall(yzbuf, scount, sdispl, xzbuf, rcount, rdispl, group)
1781 : ELSE
1782 0 : CALL group%alltoall(yzbuf, scount, sdispl, xzbuf, rcount, rdispl)
1783 : END IF
1784 : END IF
1785 :
1786 0 : myx = fft_scratch%sizes%r_pos(1)
1787 0 : myz = fft_scratch%sizes%r_pos(2)
1788 0 : nz = bo(2, 3, rs_pos) - bo(1, 3, rs_pos) + 1
1789 :
1790 : !$OMP PARALLEL DO DEFAULT(NONE), &
1791 : !$OMP PRIVATE(ipr,jj,ir,jx,jy,jz),&
1792 : !$OMP SHARED(tb,np,p2p,bo,rs_pos,nray),&
1793 : !$OMP SHARED(yzp,alltoall_sgl,zcor,myz),&
1794 0 : !$OMP SHARED(xzbuf,xzbuf_sgl,nz,rdispl)
1795 : DO ip = 0, np - 1
1796 : ipr = p2p(ip)
1797 : jj = 0
1798 : DO jx = 0, bo(2, 1, rs_pos) - bo(1, 1, rs_pos)
1799 : DO ir = 1, nray(ip)
1800 : jz = yzp(2, ir, ip)
1801 : IF (alltoall_sgl) THEN
1802 : IF (zcor(jz) == myz) THEN
1803 : jj = jj + 1
1804 : jy = yzp(1, ir, ip)
1805 : jz = jz - bo(1, 3, rs_pos) + 1
1806 : tb(jy, jz + jx*nz) = xzbuf_sgl(jj + rdispl(ipr))
1807 : END IF
1808 : ELSE
1809 : IF (zcor(jz) == myz) THEN
1810 : jj = jj + 1
1811 : jy = yzp(1, ir, ip)
1812 : jz = jz - bo(1, 3, rs_pos) + 1
1813 : tb(jy, jz + jx*nz) = xzbuf(jj + rdispl(ipr))
1814 : END IF
1815 : END IF
1816 : END DO
1817 : END DO
1818 : END DO
1819 : !$OMP END PARALLEL DO
1820 :
1821 0 : CALL timestop(handle)
1822 :
1823 0 : END SUBROUTINE yz_to_xz
1824 :
1825 : ! **************************************************************************************************
1826 : !> \brief ...
1827 : !> \param sb ...
1828 : !> \param group ...
1829 : !> \param dims ...
1830 : !> \param my_pos ...
1831 : !> \param p2p ...
1832 : !> \param yzp ...
1833 : !> \param nray ...
1834 : !> \param bo ...
1835 : !> \param tb ...
1836 : !> \param fft_scratch ...
1837 : !> \par History
1838 : !> 15. Feb. 2006 : single precision all_to_all
1839 : !> \author JGH (19-Jan-2001)
1840 : ! **************************************************************************************************
1841 0 : SUBROUTINE xz_to_yz(sb, group, dims, my_pos, p2p, yzp, nray, bo, tb, fft_scratch)
1842 :
1843 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
1844 : INTENT(IN) :: sb
1845 :
1846 : CLASS(mp_comm_type), INTENT(IN) :: group
1847 : INTEGER, DIMENSION(2), INTENT(IN) :: dims
1848 : INTEGER, INTENT(IN) :: my_pos
1849 : INTEGER, CONTIGUOUS, DIMENSION(0:), INTENT(IN) :: p2p
1850 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), INTENT(IN) :: yzp
1851 : INTEGER, CONTIGUOUS, DIMENSION(0:), INTENT(IN) :: nray
1852 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), INTENT(IN) :: bo
1853 : COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(INOUT), CONTIGUOUS :: tb
1854 : TYPE(fft_scratch_type), INTENT(INOUT) :: fft_scratch
1855 :
1856 : CHARACTER(len=*), PARAMETER :: routineN = 'xz_to_yz'
1857 :
1858 0 : COMPLEX(KIND=dp), DIMENSION(:), POINTER, CONTIGUOUS :: xzbuf, yzbuf
1859 0 : COMPLEX(KIND=sp), DIMENSION(:), POINTER, CONTIGUOUS :: xzbuf_sgl, yzbuf_sgl
1860 : INTEGER :: handle, icrs, ip, ipl, ir, ix, ixx, iz, &
1861 : jj, jx, jy, jz, mp, myx, myz, np, npx, &
1862 : npz, nx, nz
1863 0 : INTEGER, DIMENSION(:), POINTER, CONTIGUOUS :: pzcoord, rcount, rdispl, scount, sdispl, &
1864 0 : xcor, zcor
1865 0 : INTEGER, DIMENSION(:, :), CONTIGUOUS, POINTER :: pgrid
1866 :
1867 0 : CALL timeset(routineN, handle)
1868 :
1869 0 : np = SIZE(p2p)
1870 :
1871 0 : IF (alltoall_sgl) THEN
1872 0 : yzbuf_sgl => fft_scratch%yzbuf_sgl
1873 0 : xzbuf_sgl => fft_scratch%xzbuf_sgl
1874 : ELSE
1875 0 : yzbuf => fft_scratch%yzbuf
1876 0 : xzbuf => fft_scratch%xzbuf
1877 : END IF
1878 0 : npx = dims(1)
1879 0 : npz = dims(2)
1880 0 : pgrid => fft_scratch%pgrid
1881 0 : xcor => fft_scratch%xcor
1882 0 : zcor => fft_scratch%zcor
1883 0 : pzcoord => fft_scratch%pzcoord
1884 0 : scount => fft_scratch%scount
1885 0 : rcount => fft_scratch%rcount
1886 0 : sdispl => fft_scratch%sdispl
1887 0 : rdispl => fft_scratch%rdispl
1888 :
1889 : ! If the send and recv counts are not already cached, then
1890 : ! calculate and store them
1891 0 : IF (fft_scratch%in == 0) THEN
1892 :
1893 0 : rcount = 0
1894 0 : nx = MAXVAL(bo(2, 1, :))
1895 :
1896 0 : DO ix = 0, npx - 1
1897 0 : ip = pgrid(ix, 0)
1898 0 : xcor(bo(1, 1, ip):bo(2, 1, ip)) = ix
1899 : END DO
1900 0 : DO iz = 0, npz - 1
1901 0 : ip = pgrid(0, iz)
1902 0 : zcor(bo(1, 3, ip):bo(2, 3, ip)) = iz
1903 : END DO
1904 0 : DO jx = 1, nx
1905 0 : DO ir = 1, nray(my_pos)
1906 0 : jy = yzp(1, ir, my_pos)
1907 0 : jz = yzp(2, ir, my_pos)
1908 0 : ip = pgrid(xcor(jx), zcor(jz))
1909 0 : rcount(ip) = rcount(ip) + 1
1910 : END DO
1911 : END DO
1912 :
1913 0 : CALL group%alltoall(rcount, scount, 1)
1914 0 : fft_scratch%xzcount = scount
1915 0 : fft_scratch%yzcount = rcount
1916 :
1917 : ! Work out the correct displacements in the buffers
1918 0 : sdispl(0) = 0
1919 0 : rdispl(0) = 0
1920 0 : DO ip = 1, np - 1
1921 0 : sdispl(ip) = sdispl(ip - 1) + scount(ip - 1)
1922 0 : rdispl(ip) = rdispl(ip - 1) + rcount(ip - 1)
1923 : END DO
1924 :
1925 0 : fft_scratch%xzdispl = sdispl
1926 0 : fft_scratch%yzdispl = rdispl
1927 :
1928 0 : icrs = 0
1929 0 : DO ip = 0, np - 1
1930 0 : IF (scount(ip) /= 0) icrs = icrs + 1
1931 0 : IF (rcount(ip) /= 0) icrs = icrs + 1
1932 : END DO
1933 0 : CALL group%sum(icrs)
1934 0 : fft_scratch%rsratio = REAL(icrs, KIND=dp)/(REAL(2*np, KIND=dp)*REAL(np, KIND=dp))
1935 :
1936 0 : fft_scratch%in = 1
1937 : ELSE
1938 0 : scount = fft_scratch%xzcount
1939 0 : rcount = fft_scratch%yzcount
1940 0 : sdispl = fft_scratch%xzdispl
1941 0 : rdispl = fft_scratch%yzdispl
1942 : END IF
1943 :
1944 : ! Now do the actual packing
1945 0 : myx = fft_scratch%sizes%r_pos(1)
1946 0 : myz = fft_scratch%sizes%r_pos(2)
1947 0 : mp = p2p(my_pos)
1948 0 : nz = bo(2, 3, mp) - bo(1, 3, mp) + 1
1949 0 : nx = bo(2, 1, mp) - bo(1, 1, mp) + 1
1950 :
1951 : !$OMP PARALLEL DO DEFAULT(NONE), &
1952 : !$OMP PRIVATE(jj,ipl,ir,jx,jy,jz,ixx),&
1953 : !$OMP SHARED(np,p2p,nray,yzp,zcor,myz,bo,mp),&
1954 : !$OMP SHARED(alltoall_sgl,nx,scount,sdispl),&
1955 0 : !$OMP SHARED(xzbuf,xzbuf_sgl,sb,nz)
1956 : DO ip = 0, np - 1
1957 : jj = 0
1958 : ipl = p2p(ip)
1959 : DO ir = 1, nray(ip)
1960 : jz = yzp(2, ir, ip)
1961 : IF (zcor(jz) == myz) THEN
1962 : jj = jj + 1
1963 : jy = yzp(1, ir, ip)
1964 : jz = yzp(2, ir, ip) - bo(1, 3, mp) + 1
1965 : IF (alltoall_sgl) THEN
1966 : DO jx = 0, nx - 1
1967 : ixx = jj + jx*scount(ipl)/nx
1968 : xzbuf_sgl(ixx + sdispl(ipl)) = CMPLX(sb(jy, jz + jx*nz), KIND=sp)
1969 : END DO
1970 : ELSE
1971 : DO jx = 0, nx - 1
1972 : ixx = jj + jx*scount(ipl)/nx
1973 : xzbuf(ixx + sdispl(ipl)) = sb(jy, jz + jx*nz)
1974 : END DO
1975 : END IF
1976 : END IF
1977 : END DO
1978 : END DO
1979 : !$OMP END PARALLEL DO
1980 :
1981 0 : IF (alltoall_sgl) THEN
1982 0 : CALL group%alltoall(xzbuf_sgl, scount, sdispl, yzbuf_sgl, rcount, rdispl)
1983 : ELSE
1984 0 : IF (fft_scratch%rsratio < ratio_sparse_alltoall) THEN
1985 0 : CALL sparse_alltoall(xzbuf, scount, sdispl, yzbuf, rcount, rdispl, group)
1986 : ELSE
1987 0 : CALL group%alltoall(xzbuf, scount, sdispl, yzbuf, rcount, rdispl)
1988 : END IF
1989 : END IF
1990 :
1991 : !$OMP PARALLEL DO DEFAULT(NONE), &
1992 : !$OMP PRIVATE(ipl,jj,nx,ir,jx,jy,jz),&
1993 : !$OMP SHARED(p2p,pzcoord,bo,nray,my_pos,yzp),&
1994 : !$OMP SHARED(rcount,rdispl,tb,yzbuf,zcor),&
1995 0 : !$OMP SHARED(yzbuf_sgl,alltoall_sgl,np)
1996 : DO ip = 0, np - 1
1997 : IF (rcount(ip) == 0) CYCLE
1998 : ipl = p2p(ip)
1999 : jj = 0
2000 : nx = bo(2, 1, ipl) - bo(1, 1, ipl) + 1
2001 : DO ir = 1, nray(my_pos)
2002 : jz = yzp(2, ir, my_pos)
2003 : IF (zcor(jz) == pzcoord(ipl)) THEN
2004 : jj = jj + 1
2005 : jy = yzp(1, ir, my_pos)
2006 : IF (alltoall_sgl) THEN
2007 : DO jx = 0, nx - 1
2008 : tb(ir, jx + bo(1, 1, ipl)) = yzbuf_sgl(rdispl(ip) + jj + jx*rcount(ip)/nx)
2009 : END DO
2010 : ELSE
2011 : DO jx = 0, nx - 1
2012 : tb(ir, jx + bo(1, 1, ipl)) = yzbuf(rdispl(ip) + jj + jx*rcount(ip)/nx)
2013 : END DO
2014 : END IF
2015 : END IF
2016 : END DO
2017 : END DO
2018 : !$OMP END PARALLEL DO
2019 :
2020 0 : CALL timestop(handle)
2021 :
2022 0 : END SUBROUTINE xz_to_yz
2023 :
2024 : ! **************************************************************************************************
2025 : !> \brief ...
2026 : !> \param cin ...
2027 : !> \param boin ...
2028 : !> \param boout ...
2029 : !> \param sout ...
2030 : !> \param fft_scratch ...
2031 : !> \par History
2032 : !> none
2033 : !> \author JGH (20-Jan-2001)
2034 : ! **************************************************************************************************
2035 0 : SUBROUTINE cube_transpose_1(cin, boin, boout, sout, fft_scratch)
2036 :
2037 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2038 : INTENT(IN) :: cin
2039 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), &
2040 : INTENT(IN) :: boin, boout
2041 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2042 : INTENT(OUT) :: sout
2043 : TYPE(fft_scratch_type), INTENT(IN) :: fft_scratch
2044 :
2045 : CHARACTER(len=*), PARAMETER :: routineN = 'cube_transpose_1'
2046 :
2047 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2048 0 : POINTER :: rbuf
2049 : INTEGER :: handle, ip, ipl, ir, is, ixy, iz, mip, &
2050 : mz, np, nx, ny, nz
2051 0 : INTEGER, CONTIGUOUS, DIMENSION(:), POINTER :: rcount, rdispl, scount, sdispl
2052 0 : INTEGER, CONTIGUOUS, DIMENSION(:, :), POINTER :: pgrid
2053 : INTEGER, DIMENSION(2) :: dim, pos
2054 :
2055 0 : CALL timeset(routineN, handle)
2056 :
2057 0 : mip = fft_scratch%mip
2058 0 : dim = fft_scratch%dim
2059 0 : pos = fft_scratch%pos
2060 0 : scount => fft_scratch%scount
2061 0 : rcount => fft_scratch%rcount
2062 0 : sdispl => fft_scratch%sdispl
2063 0 : rdispl => fft_scratch%rdispl
2064 0 : pgrid => fft_scratch%pgcube
2065 0 : np = DIM(2)
2066 :
2067 0 : nx = boin(2, 1, mip) - boin(1, 1, mip) + 1
2068 0 : nz = boin(2, 3, mip) - boin(1, 3, mip) + 1
2069 :
2070 : !$OMP PARALLEL DO DEFAULT(NONE), &
2071 : !$OMP PRIVATE(ipl,ny), &
2072 0 : !$OMP SHARED(np,pgrid,boout,scount,sdispl,nx,nz)
2073 : DO ip = 0, np - 1
2074 : ipl = pgrid(ip, 2)
2075 : ny = boout(2, 2, ipl) - boout(1, 2, ipl) + 1
2076 : scount(ip) = nx*nz*ny
2077 : sdispl(ip) = nx*nz*(boout(1, 2, ipl) - 1)
2078 : END DO
2079 : !$OMP END PARALLEL DO
2080 0 : ny = boout(2, 2, mip) - boout(1, 2, mip) + 1
2081 0 : mz = MAXVAL(boin(2, 3, :) - boin(1, 3, :) + 1)
2082 : !$OMP PARALLEL DO DEFAULT(NONE), &
2083 : !$OMP PRIVATE(ipl,nz), &
2084 0 : !$OMP SHARED(np,pgrid,boin,nx,ny,rcount,rdispl,mz)
2085 : DO ip = 0, np - 1
2086 : ipl = pgrid(ip, 2)
2087 : nz = boin(2, 3, ipl) - boin(1, 3, ipl) + 1
2088 : rcount(ip) = nx*nz*ny
2089 : rdispl(ip) = nx*ny*mz*ip
2090 : END DO
2091 : !$OMP END PARALLEL DO
2092 :
2093 0 : rbuf => fft_scratch%rbuf1
2094 :
2095 0 : CALL fft_scratch%cart_sub_comm(2)%alltoall(cin, scount, sdispl, rbuf, rcount, rdispl)
2096 :
2097 : !$OMP PARALLEL DO DEFAULT(NONE) COLLAPSE(2) &
2098 : !$OMP PRIVATE(ip,ipl,nz,iz,is,ir) &
2099 0 : !$OMP SHARED(nx,ny,np,pgrid,boin,sout,rbuf)
2100 : DO ixy = 1, nx*ny
2101 : DO ip = 0, np - 1
2102 : ipl = pgrid(ip, 2)
2103 : nz = boin(2, 3, ipl) - boin(1, 3, ipl) + 1
2104 : DO iz = 1, nz
2105 : is = boin(1, 3, ipl) + iz - 1
2106 : ir = iz + nz*(ixy - 1)
2107 : sout(is, ixy) = rbuf(ir, ip)
2108 : END DO
2109 : END DO
2110 : END DO
2111 : !$OMP END PARALLEL DO
2112 :
2113 0 : CALL timestop(handle)
2114 :
2115 0 : END SUBROUTINE cube_transpose_1
2116 :
2117 : ! **************************************************************************************************
2118 : !> \brief ...
2119 : !> \param cin ...
2120 : !> \param boin ...
2121 : !> \param boout ...
2122 : !> \param sout ...
2123 : !> \param fft_scratch ...
2124 : ! **************************************************************************************************
2125 0 : SUBROUTINE cube_transpose_2(cin, boin, boout, sout, fft_scratch)
2126 :
2127 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2128 : INTENT(IN) :: cin
2129 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), &
2130 : INTENT(IN) :: boin, boout
2131 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2132 : INTENT(OUT) :: sout
2133 : TYPE(fft_scratch_type), INTENT(IN) :: fft_scratch
2134 :
2135 : CHARACTER(len=*), PARAMETER :: routineN = 'cube_transpose_2'
2136 :
2137 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2138 0 : POINTER :: rbuf
2139 : INTEGER :: handle, ip, ipl, ir, ixy, iz, mip, mz, &
2140 : np, nx, ny, nz
2141 0 : INTEGER, CONTIGUOUS, DIMENSION(:), POINTER :: rcount, rdispl, scount, sdispl
2142 0 : INTEGER, CONTIGUOUS, DIMENSION(:, :), POINTER :: pgrid
2143 : INTEGER, DIMENSION(2) :: dim, pos
2144 : TYPE(mp_comm_type) :: sub_group
2145 :
2146 0 : CALL timeset(routineN, handle)
2147 :
2148 0 : sub_group = fft_scratch%cart_sub_comm(2)
2149 0 : mip = fft_scratch%mip
2150 0 : dim = fft_scratch%dim
2151 0 : pos = fft_scratch%pos
2152 0 : scount => fft_scratch%scount
2153 0 : rcount => fft_scratch%rcount
2154 0 : sdispl => fft_scratch%sdispl
2155 0 : rdispl => fft_scratch%rdispl
2156 0 : pgrid => fft_scratch%pgcube
2157 0 : np = DIM(2)
2158 :
2159 0 : nx = boin(2, 1, mip) - boin(1, 1, mip) + 1
2160 0 : ny = boin(2, 2, mip) - boin(1, 2, mip) + 1
2161 0 : mz = MAXVAL(boout(2, 3, :) - boout(1, 3, :) + 1)
2162 :
2163 0 : rbuf => fft_scratch%rbuf2
2164 :
2165 : !$OMP PARALLEL DEFAULT(NONE), &
2166 : !$OMP PRIVATE(ip,ipl,nz,iz,ir), &
2167 0 : !$OMP SHARED(nx,ny,np,pgrid,boout,rbuf,cin,scount,sdispl,mz)
2168 : !$OMP DO COLLAPSE(2)
2169 : DO ixy = 1, nx*ny
2170 : DO ip = 0, np - 1
2171 : ipl = pgrid(ip, 2)
2172 : nz = boout(2, 3, ipl) - boout(1, 3, ipl) + 1
2173 : DO iz = boout(1, 3, ipl), boout(2, 3, ipl)
2174 : ir = iz - boout(1, 3, ipl) + 1 + (ixy - 1)*nz
2175 : rbuf(ir, ip) = cin(iz, ixy)
2176 : END DO
2177 : END DO
2178 : END DO
2179 : !$OMP END DO
2180 : !$OMP DO
2181 : DO ip = 0, np - 1
2182 : ipl = pgrid(ip, 2)
2183 : nz = boout(2, 3, ipl) - boout(1, 3, ipl) + 1
2184 : scount(ip) = nx*ny*nz
2185 : sdispl(ip) = nx*ny*mz*ip
2186 : END DO
2187 : !$OMP END DO
2188 : !$OMP END PARALLEL
2189 0 : nz = boout(2, 3, mip) - boout(1, 3, mip) + 1
2190 : !$OMP PARALLEL DO DEFAULT(NONE), &
2191 : !$OMP PRIVATE(ipl,ny), &
2192 0 : !$OMP SHARED(np,pgrid,boin,nx,nz,rcount,rdispl)
2193 : DO ip = 0, np - 1
2194 : ipl = pgrid(ip, 2)
2195 : ny = boin(2, 2, ipl) - boin(1, 2, ipl) + 1
2196 : rcount(ip) = nx*ny*nz
2197 : rdispl(ip) = nx*nz*(boin(1, 2, ipl) - 1)
2198 : END DO
2199 : !$OMP END PARALLEL DO
2200 :
2201 0 : CALL sub_group%alltoall(rbuf, scount, sdispl, sout, rcount, rdispl)
2202 :
2203 0 : CALL timestop(handle)
2204 :
2205 0 : END SUBROUTINE cube_transpose_2
2206 :
2207 : ! **************************************************************************************************
2208 : !> \brief ...
2209 : !> \param cin ...
2210 : !> \param boin ...
2211 : !> \param boout ...
2212 : !> \param sout ...
2213 : !> \param fft_scratch ...
2214 : ! **************************************************************************************************
2215 0 : SUBROUTINE cube_transpose_3(cin, boin, boout, sout, fft_scratch)
2216 :
2217 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2218 : INTENT(IN) :: cin
2219 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), &
2220 : INTENT(IN) :: boin, boout
2221 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2222 : INTENT(OUT) :: sout
2223 : TYPE(fft_scratch_type), INTENT(IN) :: fft_scratch
2224 :
2225 : CHARACTER(len=*), PARAMETER :: routineN = 'cube_transpose_3'
2226 :
2227 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2228 0 : POINTER :: rbuf
2229 : INTEGER :: handle, ip, ipl, ir, is, ixz, iy, lb, &
2230 : mip, my, my_id, np, num_threads, nx, &
2231 : ny, nz, ub
2232 0 : INTEGER, CONTIGUOUS, DIMENSION(:), POINTER :: rcount, rdispl, scount, sdispl
2233 0 : INTEGER, CONTIGUOUS, DIMENSION(:, :), POINTER :: pgrid
2234 : INTEGER, DIMENSION(2) :: dim, pos
2235 : TYPE(mp_comm_type) :: sub_group
2236 :
2237 0 : CALL timeset(routineN, handle)
2238 :
2239 0 : sub_group = fft_scratch%cart_sub_comm(1)
2240 0 : mip = fft_scratch%mip
2241 0 : dim = fft_scratch%dim
2242 0 : pos = fft_scratch%pos
2243 0 : np = DIM(1)
2244 0 : scount => fft_scratch%scount
2245 0 : rcount => fft_scratch%rcount
2246 0 : sdispl => fft_scratch%sdispl
2247 0 : rdispl => fft_scratch%rdispl
2248 0 : pgrid => fft_scratch%pgcube
2249 :
2250 0 : ny = boin(2, 2, mip) - boin(1, 2, mip) + 1
2251 0 : nz = boin(2, 3, mip) - boin(1, 3, mip) + 1
2252 : !$OMP PARALLEL DO DEFAULT(NONE), &
2253 : !$OMP PRIVATE(ipl, nx), &
2254 0 : !$OMP SHARED(np,pgrid,boout,ny,nz,scount,sdispl)
2255 : DO ip = 0, np - 1
2256 : ipl = pgrid(ip, 1)
2257 : nx = boout(2, 1, ipl) - boout(1, 1, ipl) + 1
2258 : scount(ip) = nx*nz*ny
2259 : sdispl(ip) = ny*nz*(boout(1, 1, ipl) - 1)
2260 : END DO
2261 : !$OMP END PARALLEL DO
2262 0 : nx = boout(2, 1, mip) - boout(1, 1, mip) + 1
2263 0 : my = MAXVAL(boin(2, 2, :) - boin(1, 2, :) + 1)
2264 : !$OMP PARALLEL DO DEFAULT(NONE), &
2265 : !$OMP PRIVATE(ipl, ny), &
2266 0 : !$OMP SHARED(np,pgrid,boin,nx,nz,my,rcount,rdispl)
2267 : DO ip = 0, np - 1
2268 : ipl = pgrid(ip, 1)
2269 : ny = boin(2, 2, ipl) - boin(1, 2, ipl) + 1
2270 : rcount(ip) = nx*nz*ny
2271 : rdispl(ip) = nx*my*nz*ip
2272 : END DO
2273 : !$OMP END PARALLEL DO
2274 :
2275 0 : rbuf => fft_scratch%rbuf3
2276 0 : num_threads = 1
2277 0 : my_id = 0
2278 : !$OMP PARALLEL DEFAULT(NONE), &
2279 : !$OMP PRIVATE(NUM_THREADS, my_id, lb, ub) &
2280 0 : !$OMP SHARED(rbuf)
2281 : !$ num_threads = MIN(omp_get_max_threads(), SIZE(rbuf, 2))
2282 : !$ my_id = omp_get_thread_num()
2283 : IF (my_id < num_threads) THEN
2284 : lb = (SIZE(rbuf, 2)*my_id)/num_threads
2285 : ub = (SIZE(rbuf, 2)*(my_id + 1))/num_threads - 1
2286 : rbuf(:, lb:ub) = 0.0_dp
2287 : END IF
2288 : !$OMP END PARALLEL
2289 :
2290 0 : CALL sub_group%alltoall(cin, scount, sdispl, rbuf, rcount, rdispl)
2291 :
2292 : !$OMP PARALLEL DO DEFAULT(NONE) COLLAPSE(2) &
2293 : !$OMP PRIVATE(ip,ipl,ny,iy,is,ir) &
2294 0 : !$OMP SHARED(nx,nz,np,pgrid,boin,rbuf,sout)
2295 : DO ixz = 1, nx*nz
2296 : DO ip = 0, np - 1
2297 : ipl = pgrid(ip, 1)
2298 : ny = boin(2, 2, ipl) - boin(1, 2, ipl) + 1
2299 : DO iy = 1, ny
2300 : is = boin(1, 2, ipl) + iy - 1
2301 : ir = iy + ny*(ixz - 1)
2302 : sout(is, ixz) = rbuf(ir, ip)
2303 : END DO
2304 : END DO
2305 : END DO
2306 : !$OMP END PARALLEL DO
2307 :
2308 0 : CALL timestop(handle)
2309 :
2310 0 : END SUBROUTINE cube_transpose_3
2311 :
2312 : ! **************************************************************************************************
2313 : !> \brief ...
2314 : !> \param cin ...
2315 : !> \param boin ...
2316 : !> \param boout ...
2317 : !> \param sout ...
2318 : !> \param fft_scratch ...
2319 : ! **************************************************************************************************
2320 0 : SUBROUTINE cube_transpose_4(cin, boin, boout, sout, fft_scratch)
2321 :
2322 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2323 : INTENT(IN) :: cin
2324 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), &
2325 : INTENT(IN) :: boin, boout
2326 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2327 : INTENT(OUT) :: sout
2328 : TYPE(fft_scratch_type), INTENT(IN) :: fft_scratch
2329 :
2330 : CHARACTER(len=*), PARAMETER :: routineN = 'cube_transpose_4'
2331 :
2332 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2333 0 : POINTER :: rbuf
2334 : INTEGER :: handle, ip, ipl, ir, iy, izx, lb, mip, &
2335 : my, my_id, np, num_threads, nx, ny, &
2336 : nz, ub
2337 0 : INTEGER, CONTIGUOUS, DIMENSION(:), POINTER :: rcount, rdispl, scount, sdispl
2338 0 : INTEGER, CONTIGUOUS, DIMENSION(:, :), POINTER :: pgrid
2339 : INTEGER, DIMENSION(2) :: dim, pos
2340 : TYPE(mp_comm_type) :: sub_group
2341 :
2342 0 : CALL timeset(routineN, handle)
2343 :
2344 0 : sub_group = fft_scratch%cart_sub_comm(1)
2345 0 : mip = fft_scratch%mip
2346 0 : dim = fft_scratch%dim
2347 0 : pos = fft_scratch%pos
2348 0 : np = DIM(1)
2349 0 : scount => fft_scratch%scount
2350 0 : rcount => fft_scratch%rcount
2351 0 : sdispl => fft_scratch%sdispl
2352 0 : rdispl => fft_scratch%rdispl
2353 0 : pgrid => fft_scratch%pgcube
2354 :
2355 0 : nx = boin(2, 1, mip) - boin(1, 1, mip) + 1
2356 0 : nz = boin(2, 3, mip) - boin(1, 3, mip) + 1
2357 0 : my = MAXVAL(boout(2, 2, :) - boout(1, 2, :) + 1)
2358 :
2359 0 : rbuf => fft_scratch%rbuf4
2360 0 : num_threads = 1
2361 0 : my_id = 0
2362 : !$OMP PARALLEL DEFAULT(NONE), &
2363 : !$OMP PRIVATE(NUM_THREADS,my_id,lb,ub,ip,ipl,ny,iy,ir), &
2364 0 : !$OMP SHARED(rbuf,nz,nx,np,pgrid,boout,cin,my,scount,sdispl)
2365 : !$ num_threads = MIN(omp_get_max_threads(), SIZE(rbuf, 2))
2366 : !$ my_id = omp_get_thread_num()
2367 : IF (my_id < num_threads) THEN
2368 : lb = (SIZE(rbuf, 2)*my_id)/num_threads
2369 : ub = (SIZE(rbuf, 2)*(my_id + 1))/num_threads - 1
2370 : rbuf(:, lb:ub) = 0.0_dp
2371 : END IF
2372 : !$OMP BARRIER
2373 :
2374 : !$OMP DO COLLAPSE(2)
2375 : DO izx = 1, nz*nx
2376 : DO ip = 0, np - 1
2377 : ipl = pgrid(ip, 1)
2378 : ny = boout(2, 2, ipl) - boout(1, 2, ipl) + 1
2379 : DO iy = boout(1, 2, ipl), boout(2, 2, ipl)
2380 : ir = iy - boout(1, 2, ipl) + 1 + (izx - 1)*ny
2381 : rbuf(ir, ip) = cin(iy, izx)
2382 : END DO
2383 : END DO
2384 : END DO
2385 : !$OMP END DO
2386 : !$OMP DO
2387 : DO ip = 0, np - 1
2388 : ipl = pgrid(ip, 1)
2389 : ny = boout(2, 2, ipl) - boout(1, 2, ipl) + 1
2390 : scount(ip) = nx*ny*nz
2391 : sdispl(ip) = nx*nz*my*ip
2392 : END DO
2393 : !$OMP END DO
2394 : !$OMP END PARALLEL
2395 0 : ny = boout(2, 2, mip) - boout(1, 2, mip) + 1
2396 : !$OMP PARALLEL DO DEFAULT(NONE), &
2397 : !$OMP PRIVATE(ipl,nx), &
2398 0 : !$OMP SHARED(np,pgrid,boin,rcount,rdispl,ny,nz)
2399 : DO ip = 0, np - 1
2400 : ipl = pgrid(ip, 1)
2401 : nx = boin(2, 1, ipl) - boin(1, 1, ipl) + 1
2402 : rcount(ip) = nx*ny*nz
2403 : rdispl(ip) = ny*nz*(boin(1, 1, ipl) - 1)
2404 : END DO
2405 : !$OMP END PARALLEL DO
2406 :
2407 0 : CALL sub_group%alltoall(rbuf, scount, sdispl, sout, rcount, rdispl)
2408 :
2409 0 : CALL timestop(handle)
2410 :
2411 0 : END SUBROUTINE cube_transpose_4
2412 :
2413 : ! **************************************************************************************************
2414 : !> \brief ...
2415 : !> \param cin ...
2416 : !> \param group ...
2417 : !> \param boin ...
2418 : !> \param boout ...
2419 : !> \param sout ...
2420 : !> \param fft_scratch ...
2421 : ! **************************************************************************************************
2422 104 : SUBROUTINE cube_transpose_5(cin, group, boin, boout, sout, fft_scratch)
2423 :
2424 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2425 : INTENT(IN) :: cin
2426 :
2427 : CLASS(mp_comm_type), INTENT(IN) :: group
2428 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), INTENT(IN) :: boin, boout
2429 : COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(OUT), CONTIGUOUS :: sout
2430 : TYPE(fft_scratch_type), INTENT(IN) :: fft_scratch
2431 :
2432 : CHARACTER(len=*), PARAMETER :: routineN = 'cube_transpose_5'
2433 :
2434 104 : COMPLEX(KIND=dp), DIMENSION(:, :), POINTER, CONTIGUOUS :: rbuf
2435 : INTEGER :: handle, ip, ir, is, ixz, iy, lb, mip, &
2436 : my, my_id, np, num_threads, nx, ny, &
2437 : nz, ub
2438 104 : INTEGER, DIMENSION(:), POINTER, CONTIGUOUS :: rcount, rdispl, scount, sdispl
2439 :
2440 104 : CALL timeset(routineN, handle)
2441 :
2442 104 : np = fft_scratch%sizes%numtask
2443 104 : mip = fft_scratch%mip
2444 104 : scount => fft_scratch%scount
2445 104 : rcount => fft_scratch%rcount
2446 104 : sdispl => fft_scratch%sdispl
2447 104 : rdispl => fft_scratch%rdispl
2448 :
2449 104 : ny = boin(2, 2, mip) - boin(1, 2, mip) + 1
2450 104 : nz = boin(2, 3, mip) - boin(1, 3, mip) + 1
2451 : !$OMP PARALLEL DO DEFAULT(NONE), &
2452 : !$OMP PRIVATE(nx), &
2453 104 : !$OMP SHARED(np,boout,ny,nz,scount,sdispl)
2454 : DO ip = 0, np - 1
2455 : nx = boout(2, 1, ip) - boout(1, 1, ip) + 1
2456 : scount(ip) = nx*nz*ny
2457 : sdispl(ip) = ny*nz*(boout(1, 1, ip) - 1)
2458 : END DO
2459 : !$OMP END PARALLEL DO
2460 104 : nx = boout(2, 1, mip) - boout(1, 1, mip) + 1
2461 312 : my = MAXVAL(boin(2, 2, :) - boin(1, 2, :) + 1)
2462 : !$OMP PARALLEL DO DEFAULT(NONE), &
2463 : !$OMP PRIVATE(ny), &
2464 104 : !$OMP SHARED(np,boin,nx,nz,rcount,rdispl,my)
2465 : DO ip = 0, np - 1
2466 : ny = boin(2, 2, ip) - boin(1, 2, ip) + 1
2467 : rcount(ip) = nx*nz*ny
2468 : rdispl(ip) = nx*my*nz*ip
2469 : END DO
2470 : !$OMP END PARALLEL DO
2471 :
2472 104 : rbuf => fft_scratch%rbuf5
2473 104 : num_threads = 1
2474 104 : my_id = 0
2475 : !$OMP PARALLEL DEFAULT(NONE), &
2476 : !$OMP PRIVATE(NUM_THREADS, my_id, lb, ub), &
2477 104 : !$OMP SHARED(rbuf)
2478 : !$ num_threads = MIN(omp_get_max_threads(), SIZE(rbuf, 2))
2479 : !$ my_id = omp_get_thread_num()
2480 : IF (my_id < num_threads) THEN
2481 : lb = (SIZE(rbuf, 2)*my_id)/num_threads
2482 : ub = (SIZE(rbuf, 2)*(my_id + 1))/num_threads - 1
2483 : rbuf(:, lb:ub) = 0.0_dp
2484 : END IF
2485 : !$OMP END PARALLEL
2486 :
2487 104 : CALL group%alltoall(cin, scount, sdispl, rbuf, rcount, rdispl)
2488 :
2489 : !$OMP PARALLEL DO DEFAULT(NONE) COLLAPSE(2) &
2490 : !$OMP PRIVATE(ip,ny,iy,is,ir) &
2491 104 : !$OMP SHARED(nx,nz,np,boin,sout,rbuf)
2492 : DO ixz = 1, nx*nz
2493 : DO ip = 0, np - 1
2494 : ny = boin(2, 2, ip) - boin(1, 2, ip) + 1
2495 : DO iy = 1, ny
2496 : is = boin(1, 2, ip) + iy - 1
2497 : ir = iy + ny*(ixz - 1)
2498 : sout(is, ixz) = rbuf(ir, ip)
2499 : END DO
2500 : END DO
2501 : END DO
2502 : !$OMP END PARALLEL DO
2503 :
2504 104 : CALL timestop(handle)
2505 :
2506 104 : END SUBROUTINE cube_transpose_5
2507 :
2508 : ! **************************************************************************************************
2509 : !> \brief ...
2510 : !> \param cin ...
2511 : !> \param group ...
2512 : !> \param boin ...
2513 : !> \param boout ...
2514 : !> \param sout ...
2515 : !> \param fft_scratch ...
2516 : ! **************************************************************************************************
2517 104 : SUBROUTINE cube_transpose_6(cin, group, boin, boout, sout, fft_scratch)
2518 :
2519 : COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
2520 : INTENT(IN) :: cin
2521 :
2522 : CLASS(mp_comm_type), INTENT(IN) :: group
2523 : INTEGER, CONTIGUOUS, DIMENSION(:, :, 0:), INTENT(IN) :: boin, boout
2524 : COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(OUT), CONTIGUOUS :: sout
2525 : TYPE(fft_scratch_type), INTENT(IN) :: fft_scratch
2526 :
2527 : CHARACTER(len=*), PARAMETER :: routineN = 'cube_transpose_6'
2528 :
2529 104 : COMPLEX(KIND=dp), DIMENSION(:, :), POINTER, CONTIGUOUS :: rbuf
2530 : INTEGER :: handle, ip, ir, iy, izx, lb, mip, my, &
2531 : my_id, np, num_threads, nx, ny, nz, ub
2532 104 : INTEGER, DIMENSION(:), POINTER, CONTIGUOUS :: rcount, rdispl, scount, sdispl
2533 :
2534 104 : CALL timeset(routineN, handle)
2535 :
2536 104 : np = fft_scratch%sizes%numtask
2537 104 : mip = fft_scratch%mip
2538 104 : scount => fft_scratch%scount
2539 104 : rcount => fft_scratch%rcount
2540 104 : sdispl => fft_scratch%sdispl
2541 104 : rdispl => fft_scratch%rdispl
2542 :
2543 104 : nx = boin(2, 1, mip) - boin(1, 1, mip) + 1
2544 104 : nz = boin(2, 3, mip) - boin(1, 3, mip) + 1
2545 312 : my = MAXVAL(boout(2, 2, :) - boout(1, 2, :) + 1)
2546 :
2547 104 : rbuf => fft_scratch%rbuf5
2548 104 : num_threads = 1
2549 104 : my_id = 0
2550 : !$OMP PARALLEL DEFAULT(NONE), &
2551 : !$OMP PRIVATE(NUM_THREADS,my_id,lb,ub,ip,ny,iy,ir), &
2552 104 : !$OMP SHARED(rbuf,nx,nz,np,boout,cin,my,scount,sdispl)
2553 : !$ num_threads = MIN(omp_get_max_threads(), SIZE(rbuf, 2))
2554 : !$ my_id = omp_get_thread_num()
2555 : IF (my_id < num_threads) THEN
2556 : lb = (SIZE(rbuf, 2)*my_id)/num_threads
2557 : ub = (SIZE(rbuf, 2)*(my_id + 1))/num_threads - 1
2558 : rbuf(:, lb:ub) = 0.0_dp
2559 : END IF
2560 : !$OMP BARRIER
2561 :
2562 : !$OMP DO COLLAPSE(2)
2563 : DO izx = 1, nz*nx
2564 : DO ip = 0, np - 1
2565 : ny = boout(2, 2, ip) - boout(1, 2, ip) + 1
2566 : DO iy = boout(1, 2, ip), boout(2, 2, ip)
2567 : ir = iy - boout(1, 2, ip) + 1 + (izx - 1)*ny
2568 : rbuf(ir, ip) = cin(iy, izx)
2569 : END DO
2570 : END DO
2571 : END DO
2572 : !$OMP END DO
2573 : !$OMP DO
2574 : DO ip = 0, np - 1
2575 : ny = boout(2, 2, ip) - boout(1, 2, ip) + 1
2576 : scount(ip) = nx*ny*nz
2577 : sdispl(ip) = nx*nz*my*ip
2578 : END DO
2579 : !$OMP END DO
2580 : !$OMP END PARALLEL
2581 104 : ny = boout(2, 2, mip) - boout(1, 2, mip) + 1
2582 : !$OMP PARALLEL DO DEFAULT(NONE), &
2583 : !$OMP PRIVATE(nx), &
2584 104 : !$OMP SHARED(np,boin,rcount,rdispl,nz,ny)
2585 : DO ip = 0, np - 1
2586 : nx = boin(2, 1, ip) - boin(1, 1, ip) + 1
2587 : rcount(ip) = nx*ny*nz
2588 : rdispl(ip) = ny*nz*(boin(1, 1, ip) - 1)
2589 : END DO
2590 : !$OMP END PARALLEL DO
2591 :
2592 104 : CALL group%alltoall(rbuf, scount, sdispl, sout, rcount, rdispl)
2593 :
2594 104 : CALL timestop(handle)
2595 :
2596 104 : END SUBROUTINE cube_transpose_6
2597 :
2598 : ! **************************************************************************************************
2599 : !> \brief ...
2600 : ! **************************************************************************************************
2601 25089 : SUBROUTINE init_fft_scratch_pool()
2602 :
2603 25089 : CALL release_fft_scratch_pool()
2604 :
2605 : ! Allocate first scratch and mark it as used
2606 25089 : ALLOCATE (fft_scratch_first)
2607 727581 : ALLOCATE (fft_scratch_first%fft_scratch)
2608 : ! this is a very special scratch, it seems, we always keep it 'most - recent' so we will never delete it
2609 25089 : fft_scratch_first%fft_scratch%last_tick = HUGE(fft_scratch_first%fft_scratch%last_tick)
2610 :
2611 25089 : init_fft_pool = init_fft_pool + 1
2612 :
2613 25089 : END SUBROUTINE init_fft_scratch_pool
2614 :
2615 : ! **************************************************************************************************
2616 : !> \brief ...
2617 : !> \param fft_scratch ...
2618 : ! **************************************************************************************************
2619 75697 : SUBROUTINE deallocate_fft_scratch_type(fft_scratch)
2620 : TYPE(fft_scratch_type), INTENT(INOUT) :: fft_scratch
2621 :
2622 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
2623 : INTEGER :: ierr
2624 : COMPLEX(KIND=dp), POINTER :: dummy_ptr_z
2625 : #endif
2626 :
2627 : ! deallocate structures
2628 75697 : IF (ASSOCIATED(fft_scratch%ziptr)) THEN
2629 15871 : CALL fft_dealloc(fft_scratch%ziptr)
2630 : END IF
2631 75697 : IF (ASSOCIATED(fft_scratch%zoptr)) THEN
2632 15871 : CALL fft_dealloc(fft_scratch%zoptr)
2633 : END IF
2634 75697 : IF (ASSOCIATED(fft_scratch%p1buf)) THEN
2635 0 : CALL fft_dealloc(fft_scratch%p1buf)
2636 : END IF
2637 75697 : IF (ASSOCIATED(fft_scratch%p2buf)) THEN
2638 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
2639 : dummy_ptr_z => fft_scratch%p2buf(1, 1)
2640 : ierr = offload_free_pinned_mem(c_loc(dummy_ptr_z))
2641 : #else
2642 0 : CALL fft_dealloc(fft_scratch%p2buf)
2643 : #endif
2644 : END IF
2645 75697 : IF (ASSOCIATED(fft_scratch%p3buf)) THEN
2646 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
2647 : dummy_ptr_z => fft_scratch%p3buf(1, 1)
2648 : ierr = offload_free_pinned_mem(c_loc(dummy_ptr_z))
2649 : #else
2650 0 : CALL fft_dealloc(fft_scratch%p3buf)
2651 : #endif
2652 : END IF
2653 75697 : IF (ASSOCIATED(fft_scratch%p4buf)) THEN
2654 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
2655 : dummy_ptr_z => fft_scratch%p4buf(1, 1)
2656 : ierr = offload_free_pinned_mem(c_loc(dummy_ptr_z))
2657 : #else
2658 0 : CALL fft_dealloc(fft_scratch%p4buf)
2659 : #endif
2660 : END IF
2661 75697 : IF (ASSOCIATED(fft_scratch%p5buf)) THEN
2662 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
2663 : dummy_ptr_z => fft_scratch%p5buf(1, 1)
2664 : ierr = offload_free_pinned_mem(c_loc(dummy_ptr_z))
2665 : #else
2666 0 : CALL fft_dealloc(fft_scratch%p5buf)
2667 : #endif
2668 : END IF
2669 75697 : IF (ASSOCIATED(fft_scratch%p6buf)) THEN
2670 0 : CALL fft_dealloc(fft_scratch%p6buf)
2671 : END IF
2672 75697 : IF (ASSOCIATED(fft_scratch%p7buf)) THEN
2673 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
2674 : dummy_ptr_z => fft_scratch%p7buf(1, 1)
2675 : ierr = offload_free_pinned_mem(c_loc(dummy_ptr_z))
2676 : #else
2677 0 : CALL fft_dealloc(fft_scratch%p7buf)
2678 : #endif
2679 : END IF
2680 75697 : IF (ASSOCIATED(fft_scratch%r1buf)) THEN
2681 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
2682 : dummy_ptr_z => fft_scratch%r1buf(1, 1)
2683 : ierr = offload_free_pinned_mem(c_loc(dummy_ptr_z))
2684 : #else
2685 34729 : CALL fft_dealloc(fft_scratch%r1buf)
2686 : #endif
2687 : END IF
2688 75697 : IF (ASSOCIATED(fft_scratch%r2buf)) THEN
2689 34729 : CALL fft_dealloc(fft_scratch%r2buf)
2690 : END IF
2691 75697 : IF (ASSOCIATED(fft_scratch%tbuf)) THEN
2692 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
2693 : dummy_ptr_z => fft_scratch%tbuf(1, 1, 1)
2694 : ierr = offload_free_pinned_mem(c_loc(dummy_ptr_z))
2695 : #else
2696 34729 : CALL fft_dealloc(fft_scratch%tbuf)
2697 : #endif
2698 : END IF
2699 75697 : IF (ASSOCIATED(fft_scratch%a1buf)) THEN
2700 8 : CALL fft_dealloc(fft_scratch%a1buf)
2701 : END IF
2702 75697 : IF (ASSOCIATED(fft_scratch%a2buf)) THEN
2703 8 : CALL fft_dealloc(fft_scratch%a2buf)
2704 : END IF
2705 75697 : IF (ASSOCIATED(fft_scratch%a3buf)) THEN
2706 8 : CALL fft_dealloc(fft_scratch%a3buf)
2707 : END IF
2708 75697 : IF (ASSOCIATED(fft_scratch%a4buf)) THEN
2709 8 : CALL fft_dealloc(fft_scratch%a4buf)
2710 : END IF
2711 75697 : IF (ASSOCIATED(fft_scratch%a5buf)) THEN
2712 8 : CALL fft_dealloc(fft_scratch%a5buf)
2713 : END IF
2714 75697 : IF (ASSOCIATED(fft_scratch%a6buf)) THEN
2715 8 : CALL fft_dealloc(fft_scratch%a6buf)
2716 : END IF
2717 75697 : IF (ASSOCIATED(fft_scratch%scount)) THEN
2718 0 : DEALLOCATE (fft_scratch%scount, fft_scratch%rcount, &
2719 34737 : fft_scratch%sdispl, fft_scratch%rdispl)
2720 : END IF
2721 75697 : IF (ASSOCIATED(fft_scratch%rr)) THEN
2722 34721 : DEALLOCATE (fft_scratch%rr)
2723 : END IF
2724 75697 : IF (ASSOCIATED(fft_scratch%xzbuf)) THEN
2725 0 : DEALLOCATE (fft_scratch%xzbuf)
2726 : END IF
2727 75697 : IF (ASSOCIATED(fft_scratch%yzbuf)) THEN
2728 0 : DEALLOCATE (fft_scratch%yzbuf)
2729 : END IF
2730 75697 : IF (ASSOCIATED(fft_scratch%xzbuf_sgl)) THEN
2731 0 : DEALLOCATE (fft_scratch%xzbuf_sgl)
2732 : END IF
2733 75697 : IF (ASSOCIATED(fft_scratch%yzbuf_sgl)) THEN
2734 0 : DEALLOCATE (fft_scratch%yzbuf_sgl)
2735 : END IF
2736 75697 : IF (ASSOCIATED(fft_scratch%ss)) THEN
2737 8 : DEALLOCATE (fft_scratch%ss)
2738 : END IF
2739 75697 : IF (ASSOCIATED(fft_scratch%tt)) THEN
2740 8 : DEALLOCATE (fft_scratch%tt)
2741 : END IF
2742 75697 : IF (ASSOCIATED(fft_scratch%pgrid)) THEN
2743 0 : DEALLOCATE (fft_scratch%pgrid)
2744 : END IF
2745 75697 : IF (ASSOCIATED(fft_scratch%pgcube)) THEN
2746 34737 : DEALLOCATE (fft_scratch%pgcube)
2747 : END IF
2748 75697 : IF (ASSOCIATED(fft_scratch%xcor)) THEN
2749 0 : DEALLOCATE (fft_scratch%xcor, fft_scratch%zcor)
2750 : END IF
2751 75697 : IF (ASSOCIATED(fft_scratch%pzcoord)) THEN
2752 0 : DEALLOCATE (fft_scratch%pzcoord)
2753 : END IF
2754 75697 : IF (ASSOCIATED(fft_scratch%xzcount)) THEN
2755 0 : DEALLOCATE (fft_scratch%xzcount, fft_scratch%yzcount)
2756 0 : DEALLOCATE (fft_scratch%xzdispl, fft_scratch%yzdispl)
2757 0 : fft_scratch%in = 0
2758 0 : fft_scratch%rsratio = 1._dp
2759 : END IF
2760 75697 : IF (ASSOCIATED(fft_scratch%rbuf1)) THEN
2761 0 : DEALLOCATE (fft_scratch%rbuf1)
2762 : END IF
2763 75697 : IF (ASSOCIATED(fft_scratch%rbuf2)) THEN
2764 0 : DEALLOCATE (fft_scratch%rbuf2)
2765 : END IF
2766 75697 : IF (ASSOCIATED(fft_scratch%rbuf3)) THEN
2767 0 : DEALLOCATE (fft_scratch%rbuf3)
2768 : END IF
2769 75697 : IF (ASSOCIATED(fft_scratch%rbuf4)) THEN
2770 0 : DEALLOCATE (fft_scratch%rbuf4)
2771 : END IF
2772 75697 : IF (ASSOCIATED(fft_scratch%rbuf5)) THEN
2773 8 : DEALLOCATE (fft_scratch%rbuf5)
2774 : END IF
2775 75697 : IF (ASSOCIATED(fft_scratch%rbuf6)) THEN
2776 8 : DEALLOCATE (fft_scratch%rbuf6)
2777 : END IF
2778 :
2779 75697 : IF (fft_scratch%cart_sub_comm(1) /= mp_comm_null) THEN
2780 0 : CALL fft_scratch%cart_sub_comm(1)%free()
2781 : END IF
2782 75697 : IF (fft_scratch%cart_sub_comm(2) /= mp_comm_null) THEN
2783 0 : CALL fft_scratch%cart_sub_comm(2)%free()
2784 : END IF
2785 :
2786 75697 : CALL fft_destroy_plan(fft_scratch%fft_plan(1))
2787 75697 : CALL fft_destroy_plan(fft_scratch%fft_plan(2))
2788 75697 : CALL fft_destroy_plan(fft_scratch%fft_plan(3))
2789 75697 : CALL fft_destroy_plan(fft_scratch%fft_plan(4))
2790 75697 : CALL fft_destroy_plan(fft_scratch%fft_plan(5))
2791 75697 : CALL fft_destroy_plan(fft_scratch%fft_plan(6))
2792 :
2793 75697 : END SUBROUTINE deallocate_fft_scratch_type
2794 :
2795 : ! **************************************************************************************************
2796 : !> \brief ...
2797 : ! **************************************************************************************************
2798 48085 : SUBROUTINE release_fft_scratch_pool()
2799 : TYPE(fft_scratch_pool_type), POINTER :: fft_scratch, fft_scratch_current
2800 :
2801 48085 : !$ CPASSERT(.NOT. omp_in_parallel() .OR. 0 == omp_get_thread_num())
2802 :
2803 48085 : IF (init_fft_pool == 0) NULLIFY (fft_scratch_first)
2804 :
2805 48085 : fft_scratch => fft_scratch_first
2806 75564 : DO
2807 123649 : IF (ASSOCIATED(fft_scratch)) THEN
2808 75564 : fft_scratch_current => fft_scratch
2809 75564 : fft_scratch => fft_scratch_current%fft_scratch_next
2810 75564 : NULLIFY (fft_scratch_current%fft_scratch_next)
2811 :
2812 75564 : CALL deallocate_fft_scratch_type(fft_scratch_current%fft_scratch)
2813 :
2814 302256 : DEALLOCATE (fft_scratch_current%fft_scratch)
2815 75564 : DEALLOCATE (fft_scratch_current)
2816 : ELSE
2817 : EXIT
2818 : END IF
2819 : END DO
2820 :
2821 48085 : init_fft_pool = 0
2822 :
2823 48085 : END SUBROUTINE release_fft_scratch_pool
2824 :
2825 : ! **************************************************************************************************
2826 : !> \brief ...
2827 : ! **************************************************************************************************
2828 4208195 : SUBROUTINE resize_fft_scratch_pool()
2829 :
2830 : INTEGER :: last_tick, nscratch
2831 : TYPE(fft_scratch_pool_type), POINTER :: fft_scratch_current, fft_scratch_old
2832 :
2833 4208195 : nscratch = 0
2834 :
2835 4208195 : last_tick = HUGE(last_tick)
2836 4208195 : NULLIFY (fft_scratch_old)
2837 :
2838 : ! start at the global pool, count, and find a deletion candidate
2839 4208195 : fft_scratch_current => fft_scratch_first
2840 22557384 : DO
2841 26765579 : IF (ASSOCIATED(fft_scratch_current)) THEN
2842 22557384 : nscratch = nscratch + 1
2843 : ! is this a candidate for deletion (i.e. least recently used, and not in use)
2844 22557384 : IF (.NOT. fft_scratch_current%fft_scratch%in_use) THEN
2845 18349189 : IF (fft_scratch_current%fft_scratch%last_tick < last_tick) THEN
2846 8688439 : last_tick = fft_scratch_current%fft_scratch%last_tick
2847 8688439 : fft_scratch_old => fft_scratch_current
2848 : END IF
2849 : END IF
2850 22557384 : fft_scratch_current => fft_scratch_current%fft_scratch_next
2851 : ELSE
2852 : EXIT
2853 : END IF
2854 : END DO
2855 :
2856 : ! we should delete a scratch
2857 4208195 : IF (nscratch > fft_pool_scratch_limit) THEN
2858 : ! note that we never deallocate the first (special) element of the list
2859 133 : IF (ASSOCIATED(fft_scratch_old)) THEN
2860 : fft_scratch_current => fft_scratch_first
2861 : DO
2862 2261 : IF (ASSOCIATED(fft_scratch_current)) THEN
2863 : ! should we delete the next in the list?
2864 2128 : IF (ASSOCIATED(fft_scratch_current%fft_scratch_next, fft_scratch_old)) THEN
2865 : ! fix the linked list
2866 133 : fft_scratch_current%fft_scratch_next => fft_scratch_old%fft_scratch_next
2867 :
2868 : ! deallocate the element
2869 133 : CALL deallocate_fft_scratch_type(fft_scratch_old%fft_scratch)
2870 532 : DEALLOCATE (fft_scratch_old%fft_scratch)
2871 133 : DEALLOCATE (fft_scratch_old)
2872 :
2873 : ELSE
2874 : fft_scratch_current => fft_scratch_current%fft_scratch_next
2875 : END IF
2876 : ELSE
2877 : EXIT
2878 : END IF
2879 : END DO
2880 :
2881 : ELSE
2882 0 : CPWARN("The number of the scratches exceeded the limit, but none could be deallocated")
2883 : END IF
2884 : END IF
2885 :
2886 4208195 : END SUBROUTINE resize_fft_scratch_pool
2887 :
2888 : ! **************************************************************************************************
2889 : !> \brief ...
2890 : !> \param fft_scratch ...
2891 : !> \param tf_type ...
2892 : !> \param n ...
2893 : !> \param fft_sizes ...
2894 : ! **************************************************************************************************
2895 4208195 : SUBROUTINE get_fft_scratch(fft_scratch, tf_type, n, fft_sizes)
2896 : TYPE(fft_scratch_type), POINTER :: fft_scratch
2897 : INTEGER, INTENT(IN) :: tf_type
2898 : INTEGER, DIMENSION(:), INTENT(IN) :: n
2899 : TYPE(fft_scratch_sizes), INTENT(IN), &
2900 : OPTIONAL :: fft_sizes
2901 :
2902 : CHARACTER(len=*), PARAMETER :: routineN = 'get_fft_scratch'
2903 :
2904 : INTEGER :: coord(2), DIM(2), handle, i, ix, iz, lg, lmax, m1, m2, &
2905 : mcx2, mcy3, mcz1, mcz2, mg, mmax, mx1, mx2, my1, my3, mz1, mz2, mz3, &
2906 : nbx, nbz, nm, nmax, nmray, np, nx, ny, nyzray, nz, pos(2)
2907 : INTEGER, DIMENSION(3) :: pcoord
2908 : LOGICAL :: equal
2909 : LOGICAL, DIMENSION(2) :: dims
2910 : TYPE(fft_scratch_pool_type), POINTER :: fft_scratch_current, &
2911 : fft_scratch_last, &
2912 : fft_scratch_new
2913 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
2914 : INTEGER :: ierr
2915 : INTEGER(KIND=C_SIZE_T) :: length
2916 : TYPE(C_PTR) :: cptr_r1buf, cptr_tbuf, &
2917 : cptr_p2buf, cptr_p3buf, cptr_p4buf, cptr_p5buf, cptr_p7buf
2918 : #endif
2919 4208195 : CALL timeset(routineN, handle)
2920 :
2921 : ! this is the place to check that the scratch_pool does not grow without limits
2922 : ! before we add a new scratch check the size of the pool and release some of the list if needed
2923 4208195 : CALL resize_fft_scratch_pool()
2924 :
2925 : ! get the required scratch
2926 4208195 : !$OMP ATOMIC
2927 : tick_fft_pool = tick_fft_pool + 1
2928 4208195 : fft_scratch_current => fft_scratch_first
2929 : DO
2930 12988803 : IF (ASSOCIATED(fft_scratch_current)) THEN
2931 12938195 : IF (fft_scratch_current%fft_scratch%in_use) THEN
2932 4208195 : fft_scratch_last => fft_scratch_current
2933 4208195 : fft_scratch_current => fft_scratch_current%fft_scratch_next
2934 4208195 : CYCLE
2935 : END IF
2936 8730000 : IF (tf_type /= fft_scratch_current%fft_scratch%tf_type) THEN
2937 458894 : fft_scratch_last => fft_scratch_current
2938 458894 : fft_scratch_current => fft_scratch_current%fft_scratch_next
2939 458894 : CYCLE
2940 : END IF
2941 21015458 : IF (.NOT. ALL(n == fft_scratch_current%fft_scratch%nfft)) THEN
2942 4023714 : fft_scratch_last => fft_scratch_current
2943 4023714 : fft_scratch_current => fft_scratch_current%fft_scratch_next
2944 4023714 : CYCLE
2945 : END IF
2946 4247392 : IF (PRESENT(fft_sizes)) THEN
2947 3585118 : IF (fft_sizes%rs_group /= fft_scratch_current%fft_scratch%group) THEN
2948 89485 : fft_scratch_last => fft_scratch_current
2949 89485 : fft_scratch_current => fft_scratch_current%fft_scratch_next
2950 89485 : CYCLE
2951 : END IF
2952 3495633 : CALL is_equal(fft_sizes, fft_scratch_current%fft_scratch%sizes, equal)
2953 3495633 : IF (.NOT. equal) THEN
2954 320 : fft_scratch_last => fft_scratch_current
2955 320 : fft_scratch_current => fft_scratch_current%fft_scratch_next
2956 320 : CYCLE
2957 : END IF
2958 : END IF
2959 : ! Success
2960 4157587 : fft_scratch => fft_scratch_current%fft_scratch
2961 4157587 : fft_scratch_current%fft_scratch%in_use = .TRUE.
2962 4157587 : EXIT
2963 : ELSE
2964 : ! We cannot find the scratch type in this pool
2965 : ! Generate a new scratch set
2966 50608 : ALLOCATE (fft_scratch_new)
2967 1315808 : ALLOCATE (fft_scratch_new%fft_scratch)
2968 :
2969 50608 : IF (tf_type /= 400) THEN
2970 34737 : fft_scratch_new%fft_scratch%sizes = fft_sizes
2971 34737 : np = fft_sizes%numtask
2972 : ALLOCATE (fft_scratch_new%fft_scratch%scount(0:np - 1), fft_scratch_new%fft_scratch%rcount(0:np - 1), &
2973 : fft_scratch_new%fft_scratch%sdispl(0:np - 1), fft_scratch_new%fft_scratch%rdispl(0:np - 1), &
2974 312633 : fft_scratch_new%fft_scratch%pgcube(0:np - 1, 2))
2975 : END IF
2976 :
2977 0 : SELECT CASE (tf_type)
2978 : CASE DEFAULT
2979 0 : CPABORT("Invalid scratch type.")
2980 : CASE (100) ! fft3d_pb: full cube distribution
2981 0 : CPASSERT(PRESENT(fft_sizes))
2982 0 : mx1 = fft_sizes%mx1
2983 0 : my1 = fft_sizes%my1
2984 0 : mx2 = fft_sizes%mx2
2985 0 : mz2 = fft_sizes%mz2
2986 0 : my3 = fft_sizes%my3
2987 0 : mz3 = fft_sizes%mz3
2988 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%a1buf, [mx1*my1, n(3)])
2989 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%a2buf, [n(3), mx1*my1])
2990 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%a3buf, [mx2*mz2, n(2)])
2991 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%a4buf, [n(2), mx2*mz2])
2992 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%a5buf, [my3*mz3, n(1)])
2993 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%a6buf, [n(1), my3*mz3])
2994 0 : fft_scratch_new%fft_scratch%group = fft_sizes%rs_group
2995 :
2996 0 : dim = fft_sizes%rs_group%num_pe_cart
2997 0 : pos = fft_sizes%rs_group%mepos_cart
2998 0 : fft_scratch_new%fft_scratch%mip = fft_sizes%rs_group%mepos
2999 0 : fft_scratch_new%fft_scratch%dim = dim
3000 0 : fft_scratch_new%fft_scratch%pos = pos
3001 0 : mcz1 = fft_sizes%mcz1
3002 0 : mcx2 = fft_sizes%mcx2
3003 0 : mcz2 = fft_sizes%mcz2
3004 0 : mcy3 = fft_sizes%mcy3
3005 0 : ALLOCATE (fft_scratch_new%fft_scratch%rbuf1(mx2*my1*mcz2, 0:DIM(2) - 1))
3006 0 : ALLOCATE (fft_scratch_new%fft_scratch%rbuf2(mx1*my1*mcz2, 0:DIM(2) - 1))
3007 0 : ALLOCATE (fft_scratch_new%fft_scratch%rbuf3(mx2*mz3*mcy3, 0:DIM(1) - 1))
3008 0 : ALLOCATE (fft_scratch_new%fft_scratch%rbuf4(mx2*mz2*mcy3, 0:DIM(1) - 1))
3009 :
3010 0 : dims = [.TRUE., .FALSE.]
3011 0 : CALL fft_scratch_new%fft_scratch%cart_sub_comm(1)%from_sub(fft_sizes%rs_group, dims)
3012 0 : dims = [.FALSE., .TRUE.]
3013 0 : CALL fft_scratch_new%fft_scratch%cart_sub_comm(2)%from_sub(fft_sizes%rs_group, dims)
3014 :
3015 : !initialise pgcube
3016 0 : DO i = 0, DIM(1) - 1
3017 0 : coord = [i, pos(2)]
3018 0 : CALL fft_sizes%rs_group%rank_cart(coord, fft_scratch_new%fft_scratch%pgcube(i, 1))
3019 : END DO
3020 0 : DO i = 0, DIM(2) - 1
3021 0 : coord = [pos(1), i]
3022 0 : CALL fft_sizes%rs_group%rank_cart(coord, fft_scratch_new%fft_scratch%pgcube(i, 2))
3023 : END DO
3024 :
3025 : !set up fft plans
3026 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(1), FWFFT, .TRUE., .FALSE., &
3027 : mx1*my1, n(3), n(3), mx1*my1, &
3028 0 : fft_scratch_new%fft_scratch%a1buf, fft_scratch_new%fft_scratch%a2buf)
3029 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(2), FWFFT, .TRUE., .FALSE., &
3030 : mx2*mz2, n(2), n(2), mx2*mz2, &
3031 0 : fft_scratch_new%fft_scratch%a3buf, fft_scratch_new%fft_scratch%a4buf)
3032 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(3), FWFFT, .TRUE., .FALSE., &
3033 : my3*mz3, n(1), n(1), my3*mz3, &
3034 0 : fft_scratch_new%fft_scratch%a5buf, fft_scratch_new%fft_scratch%a6buf)
3035 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(4), BWFFT, .FALSE., .TRUE., &
3036 : n(1), my3*mz3, n(1), my3*mz3, &
3037 0 : fft_scratch_new%fft_scratch%a6buf, fft_scratch_new%fft_scratch%a5buf)
3038 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(5), BWFFT, .FALSE., .TRUE., &
3039 : n(2), mx2*mz2, n(2), mx2*mz2, &
3040 0 : fft_scratch_new%fft_scratch%a4buf, fft_scratch_new%fft_scratch%a3buf)
3041 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(6), BWFFT, .FALSE., .TRUE., &
3042 : n(3), mx1*my1, n(3), mx1*my1, &
3043 0 : fft_scratch_new%fft_scratch%a2buf, fft_scratch_new%fft_scratch%a1buf)
3044 :
3045 : CASE (101) ! fft3d_pb: full cube distribution (dim 1)
3046 8 : CPASSERT(PRESENT(fft_sizes))
3047 8 : mx1 = fft_sizes%mx1
3048 8 : my1 = fft_sizes%my1
3049 8 : mz1 = fft_sizes%mz1
3050 8 : my3 = fft_sizes%my3
3051 8 : mz3 = fft_sizes%mz3
3052 24 : CALL fft_alloc(fft_scratch_new%fft_scratch%a1buf, [mx1*my1, n(3)])
3053 24 : CALL fft_alloc(fft_scratch_new%fft_scratch%a2buf, [n(3), mx1*my1])
3054 8 : fft_scratch_new%fft_scratch%group = fft_sizes%rs_group
3055 24 : CALL fft_alloc(fft_scratch_new%fft_scratch%a3buf, [mx1*mz1, n(2)])
3056 24 : CALL fft_alloc(fft_scratch_new%fft_scratch%a4buf, [n(2), mx1*mz1])
3057 24 : CALL fft_alloc(fft_scratch_new%fft_scratch%a5buf, [my3*mz3, n(1)])
3058 24 : CALL fft_alloc(fft_scratch_new%fft_scratch%a6buf, [n(1), my3*mz3])
3059 :
3060 24 : dim = fft_sizes%rs_group%num_pe_cart
3061 24 : pos = fft_sizes%rs_group%mepos_cart
3062 8 : fft_scratch_new%fft_scratch%mip = fft_sizes%rs_group%mepos
3063 24 : fft_scratch_new%fft_scratch%dim = dim
3064 24 : fft_scratch_new%fft_scratch%pos = pos
3065 8 : mcy3 = fft_sizes%mcy3
3066 32 : ALLOCATE (fft_scratch_new%fft_scratch%rbuf5(mx1*mz3*mcy3, 0:DIM(1) - 1))
3067 32 : ALLOCATE (fft_scratch_new%fft_scratch%rbuf6(mx1*mz1*mcy3, 0:DIM(1) - 1))
3068 :
3069 : !set up fft plans
3070 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(1), FWFFT, .TRUE., .FALSE., &
3071 : mx1*my1, n(3), n(3), mx1*my1, &
3072 8 : fft_scratch_new%fft_scratch%a1buf, fft_scratch_new%fft_scratch%a3buf)
3073 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(2), FWFFT, .TRUE., .FALSE., &
3074 : mx1*mz1, n(2), n(2), mx1*mz1, &
3075 8 : fft_scratch_new%fft_scratch%a3buf, fft_scratch_new%fft_scratch%a4buf)
3076 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(3), FWFFT, .TRUE., .FALSE., &
3077 : my3*mz3, n(1), n(1), my3*mz3, &
3078 8 : fft_scratch_new%fft_scratch%a5buf, fft_scratch_new%fft_scratch%a6buf)
3079 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(4), BWFFT, .FALSE., .TRUE., &
3080 : n(1), my3*mz3, n(1), my3*mz3, &
3081 8 : fft_scratch_new%fft_scratch%a6buf, fft_scratch_new%fft_scratch%a5buf)
3082 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(5), BWFFT, .FALSE., .TRUE., &
3083 : n(2), mx1*mz1, n(2), mx1*mz1, &
3084 8 : fft_scratch_new%fft_scratch%a4buf, fft_scratch_new%fft_scratch%a3buf)
3085 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(6), BWFFT, .FALSE., .TRUE., &
3086 : n(3), mx1*my1, n(3), mx1*my1, &
3087 8 : fft_scratch_new%fft_scratch%a3buf, fft_scratch_new%fft_scratch%a1buf)
3088 :
3089 : CASE (200) ! fft3d_ps: plane distribution
3090 34729 : CPASSERT(PRESENT(fft_sizes))
3091 34729 : nx = fft_sizes%nx
3092 34729 : ny = fft_sizes%ny
3093 34729 : nz = fft_sizes%nz
3094 34729 : mx2 = fft_sizes%mx2
3095 34729 : lmax = fft_sizes%lmax
3096 34729 : mmax = fft_sizes%mmax
3097 34729 : lg = fft_sizes%lg
3098 34729 : mg = fft_sizes%mg
3099 34729 : np = fft_sizes%numtask
3100 34729 : nmray = fft_sizes%nmray
3101 34729 : nyzray = fft_sizes%nyzray
3102 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
3103 : length = INT(2*dp_size*MAX(mmax, 1)*MAX(lmax, 1), KIND=C_SIZE_T)
3104 : ierr = offload_malloc_pinned_mem(cptr_r1buf, length)
3105 : CPASSERT(ierr == 0)
3106 : CALL c_f_pointer(cptr_r1buf, fft_scratch_new%fft_scratch%r1buf, [MAX(mmax, 1), MAX(lmax, 1)])
3107 : length = INT(2*dp_size*MAX(ny, 1)*MAX(nz, 1)*MAX(nx, 1), KIND=C_SIZE_T)
3108 : ierr = offload_malloc_pinned_mem(cptr_tbuf, length)
3109 : CPASSERT(ierr == 0)
3110 : CALL c_f_pointer(cptr_tbuf, fft_scratch_new%fft_scratch%tbuf, [MAX(ny, 1), MAX(nz, 1), MAX(nx, 1)])
3111 : #else
3112 104187 : CALL fft_alloc(fft_scratch_new%fft_scratch%r1buf, [mmax, lmax])
3113 138916 : CALL fft_alloc(fft_scratch_new%fft_scratch%tbuf, [ny, nz, nx])
3114 : #endif
3115 34729 : fft_scratch_new%fft_scratch%group = fft_sizes%rs_group
3116 104187 : CALL fft_alloc(fft_scratch_new%fft_scratch%r2buf, [lg, mg])
3117 34729 : nm = nmray*mx2
3118 34729 : IF (alltoall_sgl) THEN
3119 32 : ALLOCATE (fft_scratch_new%fft_scratch%ss(mmax, lmax))
3120 32 : ALLOCATE (fft_scratch_new%fft_scratch%tt(nm, 0:np - 1))
3121 : ELSE
3122 138884 : ALLOCATE (fft_scratch_new%fft_scratch%rr(nm, 0:np - 1))
3123 : END IF
3124 :
3125 : !set up fft plans
3126 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(1), FWFFT, .TRUE., .FALSE., &
3127 : nx*ny, nz, nz, nx*ny, &
3128 34729 : fft_scratch_new%fft_scratch%tbuf, fft_scratch_new%fft_scratch%r1buf)
3129 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(2), FWFFT, .TRUE., .FALSE., &
3130 : nx*nz, ny, ny, nx*nz, &
3131 34729 : fft_scratch_new%fft_scratch%r1buf, fft_scratch_new%fft_scratch%tbuf)
3132 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(3), FWFFT, .TRUE., .FALSE., &
3133 : nyzray, n(1), n(1), nyzray, &
3134 34729 : fft_scratch_new%fft_scratch%r1buf, fft_scratch_new%fft_scratch%r2buf)
3135 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(4), BWFFT, .FALSE., .TRUE., &
3136 : n(1), nyzray, n(1), nyzray, &
3137 34729 : fft_scratch_new%fft_scratch%r2buf, fft_scratch_new%fft_scratch%r1buf)
3138 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(5), BWFFT, .FALSE., .TRUE., &
3139 : ny, nx*nz, ny, nx*nz, &
3140 34729 : fft_scratch_new%fft_scratch%tbuf, fft_scratch_new%fft_scratch%r1buf)
3141 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(6), BWFFT, .FALSE., .TRUE., &
3142 : nz, nx*ny, nz, nx*ny, &
3143 34729 : fft_scratch_new%fft_scratch%r1buf, fft_scratch_new%fft_scratch%tbuf)
3144 :
3145 : CASE (300) ! fft3d_ps: block distribution
3146 0 : CPASSERT(PRESENT(fft_sizes))
3147 0 : mx1 = fft_sizes%mx1
3148 0 : mx2 = fft_sizes%mx2
3149 0 : my1 = fft_sizes%my1
3150 0 : mz2 = fft_sizes%mz2
3151 0 : mcx2 = fft_sizes%mcx2
3152 0 : lg = fft_sizes%lg
3153 0 : mg = fft_sizes%mg
3154 0 : nmax = fft_sizes%nmax
3155 0 : nmray = fft_sizes%nmray
3156 0 : nyzray = fft_sizes%nyzray
3157 0 : m1 = fft_sizes%r_dim(1)
3158 0 : m2 = fft_sizes%r_dim(2)
3159 0 : nbx = fft_sizes%nbx
3160 0 : nbz = fft_sizes%nbz
3161 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%p1buf, [mx1*my1, n(3)])
3162 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%p6buf, [lg, mg])
3163 : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
3164 : length = INT(2*dp_size*MAX(n(3), 1)*MAX(mx1*my1, 1), KIND=C_SIZE_T)
3165 : ierr = offload_malloc_pinned_mem(cptr_p2buf, length)
3166 : CPASSERT(ierr == 0)
3167 : CALL c_f_pointer(cptr_p2buf, fft_scratch_new%fft_scratch%p2buf, [MAX(n(3), 1), MAX(mx1*my1, 1)])
3168 : length = INT(2*dp_size*MAX(mx2*mz2, 1)*MAX(n(2), 1), KIND=C_SIZE_T)
3169 : ierr = offload_malloc_pinned_mem(cptr_p3buf, length)
3170 : CPASSERT(ierr == 0)
3171 : CALL c_f_pointer(cptr_p3buf, fft_scratch_new%fft_scratch%p3buf, [MAX(mx2*mz2, 1), MAX(n(2), 1)])
3172 : length = INT(2*dp_size*MAX(n(2), 1)*MAX(mx2*mz2, 1), KIND=C_SIZE_T)
3173 : ierr = offload_malloc_pinned_mem(cptr_p4buf, length)
3174 : CPASSERT(ierr == 0)
3175 : CALL c_f_pointer(cptr_p4buf, fft_scratch_new%fft_scratch%p4buf, [MAX(n(2), 1), MAX(mx2*mz2, 1)])
3176 : length = INT(2*dp_size*MAX(nyzray, 1)*MAX(n(1), 1), KIND=C_SIZE_T)
3177 : ierr = offload_malloc_pinned_mem(cptr_p5buf, length)
3178 : CPASSERT(ierr == 0)
3179 : CALL c_f_pointer(cptr_p5buf, fft_scratch_new%fft_scratch%p5buf, [MAX(nyzray, 1), MAX(n(1), 1)])
3180 : length = INT(2*dp_size*MAX(mg, 1)*MAX(lg, 1), KIND=C_SIZE_T)
3181 : ierr = offload_malloc_pinned_mem(cptr_p7buf, length)
3182 : CPASSERT(ierr == 0)
3183 : CALL c_f_pointer(cptr_p7buf, fft_scratch_new%fft_scratch%p7buf, [MAX(mg, 1), MAX(lg, 1)])
3184 : #else
3185 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%p2buf, [n(3), mx1*my1])
3186 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%p3buf, [mx2*mz2, n(2)])
3187 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%p4buf, [n(2), mx2*mz2])
3188 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%p5buf, [nyzray, n(1)])
3189 0 : CALL fft_alloc(fft_scratch_new%fft_scratch%p7buf, [mg, lg])
3190 : #endif
3191 0 : IF (alltoall_sgl) THEN
3192 0 : ALLOCATE (fft_scratch_new%fft_scratch%yzbuf_sgl(mg*lg))
3193 0 : ALLOCATE (fft_scratch_new%fft_scratch%xzbuf_sgl(n(2)*mx2*mz2))
3194 : ELSE
3195 0 : ALLOCATE (fft_scratch_new%fft_scratch%yzbuf(mg*lg))
3196 0 : ALLOCATE (fft_scratch_new%fft_scratch%xzbuf(n(2)*mx2*mz2))
3197 : END IF
3198 0 : ALLOCATE (fft_scratch_new%fft_scratch%pgrid(0:m1 - 1, 0:m2 - 1))
3199 0 : ALLOCATE (fft_scratch_new%fft_scratch%xcor(nbx))
3200 0 : ALLOCATE (fft_scratch_new%fft_scratch%zcor(nbz))
3201 0 : ALLOCATE (fft_scratch_new%fft_scratch%pzcoord(0:np - 1))
3202 : ALLOCATE (fft_scratch_new%fft_scratch%xzcount(0:np - 1), &
3203 0 : fft_scratch_new%fft_scratch%yzcount(0:np - 1))
3204 : ALLOCATE (fft_scratch_new%fft_scratch%xzdispl(0:np - 1), &
3205 0 : fft_scratch_new%fft_scratch%yzdispl(0:np - 1))
3206 0 : fft_scratch_new%fft_scratch%group = fft_sizes%rs_group
3207 :
3208 0 : dim = fft_sizes%rs_group%num_pe_cart
3209 0 : pos = fft_sizes%rs_group%mepos_cart
3210 0 : fft_scratch_new%fft_scratch%mip = fft_sizes%rs_group%mepos
3211 0 : fft_scratch_new%fft_scratch%dim = dim
3212 0 : fft_scratch_new%fft_scratch%pos = pos
3213 0 : mcz1 = fft_sizes%mcz1
3214 0 : mcz2 = fft_sizes%mcz2
3215 0 : ALLOCATE (fft_scratch_new%fft_scratch%rbuf1(mx2*my1*mcz2, 0:DIM(2) - 1))
3216 0 : ALLOCATE (fft_scratch_new%fft_scratch%rbuf2(mx1*my1*mcz2, 0:DIM(2) - 1))
3217 :
3218 0 : dims = [.FALSE., .TRUE.]
3219 0 : CALL fft_scratch_new%fft_scratch%cart_sub_comm(2)%from_sub(fft_sizes%rs_group, dims)
3220 :
3221 : !initialise pgcube
3222 0 : DO i = 0, DIM(2) - 1
3223 0 : coord = [pos(1), i]
3224 0 : CALL fft_sizes%rs_group%rank_cart(coord, fft_scratch_new%fft_scratch%pgcube(i, 2))
3225 : END DO
3226 :
3227 : !initialise pgrid
3228 0 : DO ix = 0, m1 - 1
3229 0 : DO iz = 0, m2 - 1
3230 0 : coord = [ix, iz]
3231 0 : CALL fft_sizes%rs_group%rank_cart(coord, fft_scratch_new%fft_scratch%pgrid(ix, iz))
3232 : END DO
3233 : END DO
3234 :
3235 : !initialise pzcoord
3236 0 : DO i = 0, np - 1
3237 0 : CALL fft_sizes%rs_group%coords(i, pcoord)
3238 0 : fft_scratch_new%fft_scratch%pzcoord(i) = pcoord(2)
3239 : END DO
3240 :
3241 : !set up fft plans
3242 : ! The scratch buffers must cover the geometry declared in each call
3243 : ! below, because the FFTW planner may write the buffers during
3244 : ! planning. The plans pair the buffers such that each of p1-p6 is
3245 : ! checked once; p7 shares the size of p6.
3246 0 : CPASSERT(SIZE(fft_scratch_new%fft_scratch%p1buf) >= mx1*my1*n(3))
3247 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(1), FWFFT, .TRUE., .FALSE., &
3248 : mx1*my1, n(3), n(3), mx1*my1, &
3249 0 : fft_scratch_new%fft_scratch%p1buf, fft_scratch_new%fft_scratch%p2buf)
3250 0 : CPASSERT(SIZE(fft_scratch_new%fft_scratch%p3buf) >= mx2*mz2*n(2))
3251 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(2), FWFFT, .TRUE., .FALSE., &
3252 : mx2*mz2, n(2), n(2), mx2*mz2, &
3253 0 : fft_scratch_new%fft_scratch%p3buf, fft_scratch_new%fft_scratch%p4buf)
3254 0 : CPASSERT(SIZE(fft_scratch_new%fft_scratch%p5buf) >= nyzray*n(1))
3255 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(3), FWFFT, .TRUE., .FALSE., &
3256 : nyzray, n(1), n(1), nyzray, &
3257 0 : fft_scratch_new%fft_scratch%p5buf, fft_scratch_new%fft_scratch%p6buf)
3258 0 : CPASSERT(SIZE(fft_scratch_new%fft_scratch%p6buf) >= n(1)*nyzray)
3259 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(4), BWFFT, .FALSE., .TRUE., &
3260 : n(1), nyzray, n(1), nyzray, &
3261 0 : fft_scratch_new%fft_scratch%p6buf, fft_scratch_new%fft_scratch%p7buf)
3262 0 : CPASSERT(SIZE(fft_scratch_new%fft_scratch%p4buf) >= n(2)*mx2*mz2)
3263 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(5), BWFFT, .FALSE., .TRUE., &
3264 : n(2), mx2*mz2, n(2), mx2*mz2, &
3265 0 : fft_scratch_new%fft_scratch%p4buf, fft_scratch_new%fft_scratch%p3buf)
3266 0 : CPASSERT(SIZE(fft_scratch_new%fft_scratch%p2buf) >= n(3)*mx1*my1)
3267 : CALL fft_create_plan_1d(fft_scratch_new%fft_scratch%fft_plan(6), BWFFT, .FALSE., .TRUE., &
3268 : n(3), mx1*my1, n(3), mx1*my1, &
3269 0 : fft_scratch_new%fft_scratch%p2buf, fft_scratch_new%fft_scratch%p1buf)
3270 :
3271 : CASE (400) ! serial FFT
3272 15871 : np = 0
3273 15871 : CALL fft_alloc(fft_scratch_new%fft_scratch%ziptr, n)
3274 15871 : CALL fft_alloc(fft_scratch_new%fft_scratch%zoptr, n)
3275 :
3276 : !in place plans
3277 : CALL fft_create_plan_3d(fft_scratch_new%fft_scratch%fft_plan(1), .TRUE., FWFFT, n, &
3278 15871 : fft_scratch_new%fft_scratch%ziptr, fft_scratch_new%fft_scratch%ziptr)
3279 : CALL fft_create_plan_3d(fft_scratch_new%fft_scratch%fft_plan(2), .TRUE., BWFFT, n, &
3280 15871 : fft_scratch_new%fft_scratch%ziptr, fft_scratch_new%fft_scratch%ziptr)
3281 : ! out of place plans
3282 : CALL fft_create_plan_3d(fft_scratch_new%fft_scratch%fft_plan(3), .FALSE., FWFFT, n, &
3283 15871 : fft_scratch_new%fft_scratch%ziptr, fft_scratch_new%fft_scratch%zoptr)
3284 : CALL fft_create_plan_3d(fft_scratch_new%fft_scratch%fft_plan(4), .FALSE., BWFFT, n, &
3285 66479 : fft_scratch_new%fft_scratch%ziptr, fft_scratch_new%fft_scratch%zoptr)
3286 :
3287 : END SELECT
3288 :
3289 50608 : NULLIFY (fft_scratch_new%fft_scratch_next)
3290 : fft_scratch_new%fft_scratch%fft_scratch_id = &
3291 50608 : fft_scratch_last%fft_scratch%fft_scratch_id + 1
3292 50608 : fft_scratch_new%fft_scratch%in_use = .TRUE.
3293 202432 : fft_scratch_new%fft_scratch%nfft = n
3294 50608 : fft_scratch_last%fft_scratch_next => fft_scratch_new
3295 50608 : fft_scratch_new%fft_scratch%tf_type = tf_type
3296 50608 : fft_scratch => fft_scratch_new%fft_scratch
3297 50608 : EXIT
3298 :
3299 : END IF
3300 : END DO
3301 :
3302 4208195 : !$OMP ATOMIC READ
3303 : fft_scratch%last_tick = tick_fft_pool
3304 :
3305 4208195 : CALL timestop(handle)
3306 :
3307 4208195 : END SUBROUTINE get_fft_scratch
3308 :
3309 : ! **************************************************************************************************
3310 : !> \brief ...
3311 : !> \param fft_scratch ...
3312 : ! **************************************************************************************************
3313 4208195 : SUBROUTINE release_fft_scratch(fft_scratch)
3314 :
3315 : TYPE(fft_scratch_type), POINTER :: fft_scratch
3316 :
3317 : INTEGER :: scratch_id
3318 : TYPE(fft_scratch_pool_type), POINTER :: fft_scratch_current
3319 :
3320 4208195 : scratch_id = fft_scratch%fft_scratch_id
3321 :
3322 4208195 : fft_scratch_current => fft_scratch_first
3323 8780608 : DO
3324 12988803 : IF (ASSOCIATED(fft_scratch_current)) THEN
3325 12988803 : IF (scratch_id == fft_scratch_current%fft_scratch%fft_scratch_id) THEN
3326 4208195 : fft_scratch%in_use = .FALSE.
3327 4208195 : NULLIFY (fft_scratch)
3328 4208195 : EXIT
3329 : END IF
3330 8780608 : fft_scratch_current => fft_scratch_current%fft_scratch_next
3331 : ELSE
3332 : ! We cannot find the scratch type in this pool
3333 0 : CPABORT("Invalid scratch type.")
3334 0 : EXIT
3335 : END IF
3336 : END DO
3337 :
3338 4208195 : END SUBROUTINE release_fft_scratch
3339 :
3340 : ! **************************************************************************************************
3341 : !> \brief ...
3342 : !> \param rs ...
3343 : !> \param scount ...
3344 : !> \param sdispl ...
3345 : !> \param rq ...
3346 : !> \param rcount ...
3347 : !> \param rdispl ...
3348 : !> \param group ...
3349 : ! **************************************************************************************************
3350 0 : SUBROUTINE sparse_alltoall(rs, scount, sdispl, rq, rcount, rdispl, group)
3351 : COMPLEX(KIND=dp), DIMENSION(:), POINTER :: rs
3352 : INTEGER, DIMENSION(:), POINTER :: scount, sdispl
3353 : COMPLEX(KIND=dp), DIMENSION(:), POINTER :: rq
3354 : INTEGER, DIMENSION(:), POINTER :: rcount, rdispl
3355 :
3356 : CLASS(mp_comm_type), INTENT(IN) :: group
3357 :
3358 0 : COMPLEX(KIND=dp), DIMENSION(:), POINTER :: msgin, msgout
3359 : INTEGER :: ip, n, nr, ns, pos
3360 0 : TYPE(mp_request_type), ALLOCATABLE, DIMENSION(:) :: rreq, sreq
3361 :
3362 0 : CALL group%sync()
3363 0 : n = group%num_pe
3364 0 : pos = group%mepos
3365 0 : ALLOCATE (sreq(0:n - 1))
3366 0 : ALLOCATE (rreq(0:n - 1))
3367 0 : nr = 0
3368 0 : DO ip = 0, n - 1
3369 0 : IF (rcount(ip) == 0) CYCLE
3370 0 : IF (ip == pos) CYCLE
3371 0 : msgout => rq(rdispl(ip) + 1:rdispl(ip) + rcount(ip))
3372 0 : CALL group%irecv(msgout, ip, rreq(nr))
3373 0 : nr = nr + 1
3374 : END DO
3375 0 : ns = 0
3376 0 : DO ip = 0, n - 1
3377 0 : IF (scount(ip) == 0) CYCLE
3378 0 : IF (ip == pos) CYCLE
3379 0 : msgin => rs(sdispl(ip) + 1:sdispl(ip) + scount(ip))
3380 0 : CALL group%isend(msgin, ip, sreq(ns))
3381 0 : ns = ns + 1
3382 : END DO
3383 0 : IF (rcount(pos) /= 0) THEN
3384 0 : IF (rcount(pos) /= scount(pos)) CPABORT("Invalid count.")
3385 0 : rq(rdispl(pos) + 1:rdispl(pos) + rcount(pos)) = rs(sdispl(pos) + 1:sdispl(pos) + scount(pos))
3386 : END IF
3387 0 : CALL mp_waitall(sreq(0:ns - 1))
3388 0 : CALL mp_waitall(rreq(0:nr - 1))
3389 0 : DEALLOCATE (sreq)
3390 0 : DEALLOCATE (rreq)
3391 0 : CALL group%sync()
3392 :
3393 0 : END SUBROUTINE sparse_alltoall
3394 :
3395 : ! **************************************************************************************************
3396 : !> \brief test data structures for equality. It is assumed that if they are
3397 : !> different for one mpi task they are different for all (??)
3398 : !> \param fft_size_1 ...
3399 : !> \param fft_size_2 ...
3400 : !> \param equal ...
3401 : ! **************************************************************************************************
3402 3495633 : SUBROUTINE is_equal(fft_size_1, fft_size_2, equal)
3403 : TYPE(fft_scratch_sizes) :: fft_size_1, fft_size_2
3404 : LOGICAL :: equal
3405 :
3406 : equal = .TRUE.
3407 :
3408 3495633 : equal = equal .AND. fft_size_1%nx == fft_size_2%nx
3409 3495633 : equal = equal .AND. fft_size_1%ny == fft_size_2%ny
3410 3495633 : equal = equal .AND. fft_size_1%nz == fft_size_2%nz
3411 :
3412 3495633 : equal = equal .AND. fft_size_1%lmax == fft_size_2%lmax
3413 3495633 : equal = equal .AND. fft_size_1%mmax == fft_size_2%mmax
3414 3495633 : equal = equal .AND. fft_size_1%nmax == fft_size_2%nmax
3415 :
3416 3495633 : equal = equal .AND. fft_size_1%mx1 == fft_size_2%mx1
3417 3495633 : equal = equal .AND. fft_size_1%mx2 == fft_size_2%mx2
3418 3495633 : equal = equal .AND. fft_size_1%mx3 == fft_size_2%mx3
3419 :
3420 3495633 : equal = equal .AND. fft_size_1%my1 == fft_size_2%my1
3421 3495633 : equal = equal .AND. fft_size_1%my2 == fft_size_2%my2
3422 3495633 : equal = equal .AND. fft_size_1%my3 == fft_size_2%my3
3423 :
3424 3495633 : equal = equal .AND. fft_size_1%mcz1 == fft_size_2%mcz1
3425 3495633 : equal = equal .AND. fft_size_1%mcx2 == fft_size_2%mcx2
3426 3495633 : equal = equal .AND. fft_size_1%mcz2 == fft_size_2%mcz2
3427 3495633 : equal = equal .AND. fft_size_1%mcy3 == fft_size_2%mcy3
3428 :
3429 3495633 : equal = equal .AND. fft_size_1%lg == fft_size_2%lg
3430 3495633 : equal = equal .AND. fft_size_1%mg == fft_size_2%mg
3431 :
3432 3495633 : equal = equal .AND. fft_size_1%nbx == fft_size_2%nbx
3433 3495633 : equal = equal .AND. fft_size_1%nbz == fft_size_2%nbz
3434 :
3435 3495633 : equal = equal .AND. fft_size_1%nmray == fft_size_2%nmray
3436 3495633 : equal = equal .AND. fft_size_1%nyzray == fft_size_2%nyzray
3437 :
3438 3495633 : equal = equal .AND. fft_size_1%rs_group == fft_size_2%rs_group
3439 :
3440 10486899 : equal = equal .AND. ALL(fft_size_1%g_pos == fft_size_2%g_pos)
3441 10486899 : equal = equal .AND. ALL(fft_size_1%r_pos == fft_size_2%r_pos)
3442 10486899 : equal = equal .AND. ALL(fft_size_1%r_dim == fft_size_2%r_dim)
3443 :
3444 3495633 : equal = equal .AND. fft_size_1%numtask == fft_size_2%numtask
3445 :
3446 3495633 : END SUBROUTINE is_equal
3447 :
3448 0 : END MODULE fft_tools
|