12 use fftw_mod,
only : c_double_complex, c_ptr, fftw_backward, fftw_forward, fftw_estimate, fftw_plan_many_dft_r2c, &
13 fftw_plan_many_dft_c2r, fftw_execute_dft_c2r, fftw_execute_dft_r2c, fftw_destroy_plan
14 use mpi,
only : mpi_double_complex, mpi_int, mpi_comm_self
23 integer :: my_pencil_size(3), process_decomposition_layout(3), my_process_location(3), dim
24 integer,
dimension(:),
allocatable :: send_sizes, send_offsets, recv_sizes, recv_offsets
25 integer,
dimension(:,:),
allocatable :: recv_dims, send_dims
37 complex(C_DOUBLE_COMPLEX),
dimension(:,:,:),
contiguous,
pointer ::
buffer1,
buffer2
53 integer,
intent(out) :: my_y_start, my_x_start
56 integer :: ierr, y_distinct_sizes(current_state%parallel%dim_sizes(
y_index)), &
57 x_distinct_sizes(current_state%parallel%dim_sizes(
x_index))
62 if (current_state%parallel%dim_sizes(
y_index) .gt. 1 .and. current_state%parallel%dim_sizes(
x_index) .gt. 1)
then
63 call mpi_cart_sub(current_state%parallel%neighbour_comm, (/1,0/),
dim_y_comm, ierr)
64 call mpi_cart_sub(current_state%parallel%neighbour_comm, (/0,1/),
dim_x_comm, ierr)
66 call mpi_allgather(current_state%local_grid%size(
y_index), 1, mpi_int, y_distinct_sizes, 1, mpi_int,
dim_y_comm, ierr)
67 call mpi_allgather(current_state%local_grid%size(
x_index), 1, mpi_int, x_distinct_sizes, 1, mpi_int,
dim_x_comm, ierr)
68 else if (current_state%parallel%dim_sizes(
y_index) .gt. 1)
then
69 dim_y_comm=current_state%parallel%monc_communicator
71 call mpi_allgather(current_state%local_grid%size(
y_index), 1, mpi_int, y_distinct_sizes, 1, mpi_int,
dim_y_comm, ierr)
72 x_distinct_sizes=current_state%local_grid%size(
x_index)
73 else if (current_state%parallel%dim_sizes(
x_index) .gt. 1)
then
75 dim_x_comm=current_state%parallel%monc_communicator
76 y_distinct_sizes=current_state%local_grid%size(
y_index)
77 call mpi_allgather(current_state%local_grid%size(
x_index), 1, mpi_int, x_distinct_sizes, 1, mpi_int,
dim_x_comm, ierr)
81 y_distinct_sizes=current_state%local_grid%size(
y_index)
82 x_distinct_sizes=current_state%local_grid%size(
x_index)
93 integer,
intent(in) :: monc_communicator
175 integer,
dimension(:),
intent(in) :: y_distinct_sizes, x_distinct_sizes
198 y_distinct_sizes,
backward, (/ -1 /))
216 process_dim_sizes, direction, extended_dimensions)
219 integer,
dimension(:),
intent(in) :: process_dim_sizes
220 integer,
intent(in) :: new_pencil_dim, direction, extended_dimensions(:)
223 new_pencil_dim, existing_transposition%dim, existing_transposition%process_decomposition_layout)
226 existing_transposition%dim, existing_transposition%my_process_location)
229 create_transposition%my_process_location, existing_transposition, global_grid, extended_dimensions)
241 existing_transposition%process_decomposition_layout, global_grid, extended_dimensions,
create_transposition%recv_dims)
243 existing_transposition%my_pencil_size, existing_transposition%process_decomposition_layout, &
267 type(model_state_type),
target,
intent(inout) :: current_state
268 real(kind=default_precision),
dimension(:,:,:),
intent(inout) :: source_data
269 real(kind=default_precision),
dimension(:,:,:),
intent(out) :: real_buffer
270 complex(C_DOUBLE_COMPLEX),
dimension(:,:,:),
contiguous,
pointer,
intent(out) :: buffer
289 type(model_state_type),
target,
intent(inout) :: current_state
290 real(kind=default_precision),
dimension(:,:,:),
intent(inout) :: source_data
291 real(kind=default_precision),
dimension(:,:,:),
intent(out) :: real_buffer
292 complex(C_DOUBLE_COMPLEX),
dimension(:,:,:),
contiguous,
pointer,
intent(out) :: buffer
310 type(model_state_type),
target,
intent(inout) :: current_state
311 complex(C_DOUBLE_COMPLEX),
dimension(:,:,:),
contiguous,
pointer,
intent(out) :: buffer2
312 real(kind=default_precision),
dimension(:,:,:),
intent(inout) ::
buffer1, buffer3
332 type(model_state_type),
target,
intent(inout) :: current_state
333 real(kind=default_precision),
dimension(:,:,:),
intent(inout) :: source_data
334 real(kind=default_precision),
dimension(:,:,:),
intent(out) :: real_buffer
335 complex(C_DOUBLE_COMPLEX),
dimension(:,:,:),
contiguous,
pointer,
intent(out) :: buffer
357 subroutine transpose_to_pencil(transposition_description, source_dims, communicator, direction, source_data, target_data)
359 integer,
intent(in) :: source_dims(3), communicator, direction
360 real(kind=default_precision),
dimension(:,:,:),
intent(in) :: source_data
361 real(kind=default_precision),
dimension(:,:,:),
intent(out) :: target_data
364 real(kind=default_precision),
dimension(:,:,:),
allocatable :: real_temp
365 real(kind=default_precision),
dimension(:),
allocatable :: real_temp2
368 allocate(real_temp(
size(source_data,3),
size(source_data,2),
size(source_data,1)), &
369 real_temp2(product(transposition_description%my_pencil_size)+1))
373 call mpi_alltoallv(real_temp, transposition_description%send_sizes, transposition_description%send_offsets, &
374 precision_type, real_temp2, transposition_description%recv_sizes, transposition_description%recv_offsets, &
375 precision_type, communicator, ierr)
376 call contiguise_data(transposition_description, (/source_dims(3), source_dims(2), source_dims(1)/), direction, &
377 source_real_buffer=real_temp2, target_real_buffer=target_data)
378 deallocate(real_temp, real_temp2)
389 subroutine contiguise_data(transposition_description, source_dims, direction, source_real_buffer, target_real_buffer)
390 integer,
intent(in) :: source_dims(3), direction
392 real(kind=default_precision),
dimension(:),
intent(in) :: source_real_buffer
393 real(kind=default_precision),
dimension(:,:,:),
intent(out) :: target_real_buffer
395 integer :: number_blocks, i, j, k, n, index_prefix, index_prefix_dim, block_offset, source_index
397 number_blocks=
size(transposition_description%recv_sizes)
400 index_prefix_dim=merge(2,1, direction ==
forward)
403 index_prefix=index_prefix+transposition_description%recv_dims(source_dims(index_prefix_dim), i-1)
404 block_offset=block_offset+transposition_description%recv_sizes(i-1)
407 do j=1, transposition_description%recv_dims(source_dims(3), i)
408 do k=1, transposition_description%recv_dims(source_dims(1), i)
409 do n=1, transposition_description%recv_dims(source_dims(2), i)
410 source_index=block_offset+(j-1)* transposition_description%recv_dims(source_dims(1), i)* &
411 transposition_description%recv_dims(source_dims(2), i)+ (n-1)* &
412 transposition_description%recv_dims(source_dims(1), i)+k
414 target_real_buffer(index_prefix+n, k, j)=source_real_buffer(source_index)
416 target_real_buffer(index_prefix+k, j, n)=source_real_buffer(source_index)
430 subroutine perform_r2c_fft(source_data, transformed_data, row_size, num_rows, plan_id)
431 real(kind=default_precision),
dimension(:,:,:),
contiguous,
pointer,
intent(inout) :: source_data
432 complex(C_DOUBLE_COMPLEX),
dimension(:,:,:),
contiguous,
pointer,
intent(inout) :: transformed_data
433 integer,
intent(in) :: row_size, num_rows, plan_id
436 fftw_plan(plan_id) = fftw_plan_many_dft_r2c(1, (/row_size/), num_rows, source_data, (/row_size/), 1, row_size, &
437 transformed_data, (/row_size/), 1, row_size/2+1, fftw_estimate)
440 call fftw_execute_dft_r2c(
fftw_plan(plan_id), source_data, transformed_data)
449 subroutine perform_c2r_fft(source_data, transformed_data, row_size, num_rows, plan_id)
450 complex(C_DOUBLE_COMPLEX),
dimension(:,:,:),
contiguous,
pointer,
intent(inout) :: source_data
451 real(kind=default_precision),
dimension(:,:,:),
contiguous,
pointer,
intent(inout) :: transformed_data
452 integer,
intent(in) :: row_size, num_rows, plan_id
457 fftw_plan(plan_id) = fftw_plan_many_dft_c2r(1, (/row_size/), num_rows, source_data, (/row_size/2+1/), 1, row_size/2+1, &
458 transformed_data, (/row_size/), 1, row_size, fftw_estimate)
461 call fftw_execute_dft_c2r(
fftw_plan(plan_id), source_data, transformed_data)
469 real(kind=default_precision),
dimension(:,:,:),
intent(in) :: real_source
470 real(kind=default_precision),
dimension(:,:,:),
intent(out) :: real_target
474 do i=1,
size(real_source,2)
475 real_target(:,i,:)=transpose(real_source(:,i,:))
489 global_grid, extended_dimensions, specific_sizes_per_dim)
490 integer,
intent(in) :: existing_pencil_dim, existing_pencil_size(:), new_pencil_procs_per_dim(:), extended_dimensions(:)
491 type(global_grid_type),
intent(inout) :: global_grid
492 integer,
dimension(:,:),
intent(inout) :: specific_sizes_per_dim
494 integer :: i, split_size, split_remainder, j, s
497 if (i == existing_pencil_dim)
then
498 s=global_grid%size(i)
500 split_size = s / new_pencil_procs_per_dim(i)
501 split_remainder = s - split_size * new_pencil_procs_per_dim(i)
502 do j=1,new_pencil_procs_per_dim(existing_pencil_dim)
503 specific_sizes_per_dim(i,j)=merge(split_size+1, split_size, j .le. split_remainder)
506 specific_sizes_per_dim(i,:) = existing_pencil_size(i)
514 integer,
intent(in) :: source_sizes(:)
515 integer,
dimension(:),
intent(inout) :: determined_offsets
519 determined_offsets(1)=0
520 do i=2,
size(source_sizes)
521 determined_offsets(i)=determined_offsets(i-1)+source_sizes(i-1)
532 integer,
intent(in) :: new_pencil_dim, existing_pencil_dim, existing_pencil_procs(3)
538 if (i == new_pencil_dim)
then
540 else if (i == existing_pencil_dim)
then
554 integer,
intent(in) :: new_pencil_dim, existing_pencil_dim, existing_locations(3)
560 if (i == new_pencil_dim)
then
562 else if (i == existing_pencil_dim)
then
574 integer,
dimension(:,:),
intent(in) :: dims
575 integer,
dimension(:),
intent(inout) :: concatenated_dim_sizes
580 concatenated_dim_sizes(i)=product(dims(:,i))
593 my_pencil_size, pencil_processes_per_dim, specific_sizes_per_dim)
594 integer,
intent(in) :: new_pencil_dim, existing_pencil_dim, proc_sizes(:), my_pencil_size(:), pencil_processes_per_dim(:)
595 integer,
dimension(:,:),
intent(inout) :: specific_sizes_per_dim
599 do i=1,pencil_processes_per_dim(existing_pencil_dim)
601 if (j==new_pencil_dim)
then
602 specific_sizes_per_dim(j, i)=proc_sizes(i)
604 specific_sizes_per_dim(j, i)=my_pencil_size(j)
614 type(model_state_type),
intent(inout) :: current_state
633 global_grid, extended_dimensions)
636 integer,
intent(in) :: new_pencil_dim, pencil_process_layout(3), my_pencil_location(3), extended_dimensions(:)
637 type(global_grid_type),
intent(inout) :: global_grid
640 integer :: i, split_size, split_remainder, s
643 if (i == new_pencil_dim)
then
650 else if (i == existing_transposition%dim)
then
651 s=global_grid%size(i)
654 split_size=s/pencil_process_layout(i)
655 split_remainder=s - split_size * pencil_process_layout(i)
656 determine_pencil_size(i)=merge(split_size+1, split_size, my_pencil_location(i)+1 .le. split_remainder)
668 integer,
intent(in) :: dimension, extended_dimensions(:)
671 do i=1,
size(extended_dimensions)
672 if (extended_dimensions(i) == dimension)
then
685 integer,
dimension(:),
intent(in) :: process_dim_sizes
688 integer :: temp_total, split_size, remainder
690 temp_total=(sum(process_dim_sizes) /2 + 1) * 2
691 split_size=temp_total/
size(process_dim_sizes)
692 remainder=temp_total - split_size*
size(process_dim_sizes)
705 complex(C_DOUBLE_COMPLEX),
dimension(:,:,:),
intent(in) :: complex_data
706 real(kind=default_precision),
dimension(:,:,:),
intent(out) :: real_data
710 do i=1,
size(real_data,3)
711 do j=1,
size(real_data,2)
712 do k=1,
size(real_data,1),2
713 real_data(k,j,i)=real(real(complex_data((k+1)/2,j,i)), kind=default_precision)
714 real_data(k+1,j,i)=real(aimag(complex_data((k+1)/2,j,i)), kind=default_precision)
727 real(kind=default_precision),
dimension(:,:,:),
intent(in) :: real_data
728 complex(C_DOUBLE_COMPLEX),
dimension(:,:,:),
contiguous,
pointer,
intent(out) :: complex_data
732 complex_data=cmplx(0.0d0, 0.0d0, kind=c_double_complex)
734 do i=1,
size(real_data,3)
735 do j=1,
size(real_data,2)
736 do k=1,
size(real_data,1),2
737 complex_data((k+1)/2,j,i)=cmplx(real_data(k,j,i), real_data(k+1,j,i), kind=c_double_complex)
752 type(model_state_type),
intent(inout) :: current_state
753 integer,
intent(in) :: dimension
755 integer complex_size, distributed_size, remainder, larger_nums, smaller_nums
757 complex_size=(current_state%global_grid%size(dimension)/2+1)*2
758 distributed_size=complex_size / current_state%parallel%dim_sizes(dimension)
759 remainder=complex_size - distributed_size * current_state%parallel%dim_sizes(dimension)
760 larger_nums=min(remainder, current_state%parallel%my_coords(dimension))
761 smaller_nums=current_state%parallel%my_coords(dimension)-remainder
762 deduce_my_global_start=((distributed_size+1)*larger_nums + merge(distributed_size*smaller_nums, 0, smaller_nums .gt. 0)) + 1