-
Antoine Cyril David Hoffmann authored
+ explanation of the structure
Antoine Cyril David Hoffmann authored+ explanation of the structure
ghosts_mod.F90 8.86 KiB
module ghosts
USE mpi
USE prec_const, ONLY: xp, mpi_xp_c
IMPLICIT NONE
INTEGER :: status(MPI_STATUS_SIZE), source, dest, count, ipg
PUBLIC :: update_ghosts_moments, update_ghosts_EM
CONTAINS
SUBROUTINE update_ghosts_moments
USE grid, ONLY: total_nz
USE parallel, ONLY: num_procs_p
IMPLICIT NONE
IF (num_procs_p .GT. 1) THEN ! Do it only if we share the p
CALL update_ghosts_p_mom
ENDIF
IF(total_nz .GT. 1) THEN
CALL update_ghosts_z_mom
ENDIF
END SUBROUTINE update_ghosts_moments
SUBROUTINE update_ghosts_EM
USE model, ONLY : beta
USE grid, ONLY: total_nz
USE fields, ONLY: phi, psi
IMPLICIT NONE
IF(total_nz .GT. 1) THEN
CALL update_ghosts_z_3D(phi)
IF(beta .GT. 0._xp) &
CALL update_ghosts_z_3D(psi)
ENDIF
END SUBROUTINE update_ghosts_EM
!Communicate p+1, p+2 moments to left neighboor and p-1, p-2 moments to right one
! [a b|C D|e f] : proc n has moments a to f where a,b,e,f are ghosts
!
!proc 0: [0 1 2 3 4|5 6]
! V V ^ ^
!proc 1: [3 4|5 6 7 8|9 10]
! V V ^ ^
!proc 2: [7 8|9 10 11 12|13 14]
! V V ^ ^
!proc 3: [11 12|13 14 15 16|17 18]
! ^ ^
!Closure by zero truncation : 0 0
!Communicate p+1, p+2 moments to left neighboor and p-1, p-2 moments to right one
SUBROUTINE update_ghosts_p_mom
USE time_integration, ONLY: updatetlevel
USE fields, ONLY: moments
USE parallel, ONLY: nbr_R,nbr_L,comm0, exchange_ghosts_1D
USE grid, ONLY: local_na,local_np,local_nj,local_nky,local_nkx,local_nz,&
ngp,ngj,ngz
IMPLICIT NONE
INTEGER :: ierr, first, last, count
first = 1 + ngp/2
last = local_np + ngp/2
count = (ngp/2)*local_na*(local_nj+ngj)*local_nky*local_nkx*(local_nz+ngz) ! Number of elements to send
!!!!!! Send to the right, receive from the left
CALL mpi_sendrecv(moments(:,(last-(ngp/2-1)):(last),:,:,:,:,updatetlevel), count, mpi_xp_c, nbr_R, 14, &
moments(:,(first-ngp/2):(first-1),:,:,:,:,updatetlevel), count, mpi_xp_c, nbr_L, 14, &
comm0, status, ierr)
!!!!!!! Send to the left, receive from the right
CALL mpi_sendrecv(moments(:,(first):(first+(ngp/2-1)),:,:,:,:,updatetlevel), count, mpi_xp_c, nbr_L, 16, &
moments(:,(last+1):(last+ngp/2) ,:,:,:,:,updatetlevel), count, mpi_xp_c, nbr_R, 16, &
comm0, status, ierr)
END SUBROUTINE update_ghosts_p_mom
!Communicate z+1, z+2 moments to left neighboor and z-1, z-2 moments to right one
! [a b|C D|e f] : proc n has moments a to f where a,b,e,f are ghosts
!
!proc 0: [0 1 2 3 4|5 6]
! V V ^ ^
!proc 1: [3 4|5 6 7 8|9 10]
! V V ^ ^
!proc 2: [7 8|9 10 11 12|13 14]
! V V ^ ^
!proc 3: [11 12|13 14 15 16|17 18]
! ^ ^
!Periodic: 0 1
SUBROUTINE update_ghosts_z_mom
USE geometry, ONLY: ikx_zBC_L, ikx_zBC_R, pb_phase_L, pb_phase_R
USE time_integration, ONLY: updatetlevel
USE parallel, ONLY: comm0,nbr_U,nbr_D,num_procs_z
USE fields, ONLY: moments
USE grid, ONLY: local_na,local_np,local_nj,local_nky,local_nkx,local_nz,&
ngp,ngj,ngz
IMPLICIT NONE
!! buffer for data exchanges
COMPLEX(xp),DIMENSION(local_na,local_np+ngp,local_nj+ngj,local_nky,local_nkx,-Ngz/2:Ngz/2) :: buff_pjxy_zBC
INTEGER :: ikxBC_L, ikxBC_R, ikx, iky, first, last, ig, ierr
first = 1 + ngz/2
last = local_nz + ngz/2
count = local_na*(local_np+ngp)*(local_nj+ngj)*local_nky*local_nkx
IF (num_procs_z .GT. 1) THEN
!!!!!!!!!!! Send ghost to up neighbour !!!!!!!!!!!!!!!!!!!!!!
! Send the last local moment to fill the -1 neighbour ghost
DO ig=1,ngz/2
CALL mpi_sendrecv(moments(:,:,:,:,:,last-(ig-1),updatetlevel),count,mpi_xp_c,nbr_U,24+ig, & ! Send to Up the last
buff_pjxy_zBC(:,:,:,:,:,-ig),count,mpi_xp_c,nbr_D,24+ig, & ! Recieve from Down the first-1
comm0, status, ierr)
ENDDO
!!!!!!!!!!! Send ghost to down neighbour !!!!!!!!!!!!!!!!!!!!!!
DO ig=1,ngz/2
CALL mpi_sendrecv(moments(:,:,:,:,:,first+(ig-1),updatetlevel),count,mpi_xp_c,nbr_D,26+ig, & ! Send to Up the last
buff_pjxy_zBC(:,:,:,:,:,ig),count,mpi_xp_c,nbr_U,26+ig, & ! Recieve from Down the first-1
comm0, status, ierr)
ENDDO
ELSE !No parallel (just copy)
DO ig=1,ngz/2
buff_pjxy_zBC(:,:,:,:,:,-ig) = moments(:,:,:,:,:, last-(ig-1),updatetlevel)
buff_pjxy_zBC(:,:,:,:,:, ig) = moments(:,:,:,:,:,first+(ig-1),updatetlevel)
ENDDO
ENDIF
DO iky = 1,local_nky
DO ikx = 1,local_nkx
ikxBC_L = ikx_zBC_L(iky,ikx);
! Exchanging the modes that have a periodic pair (from sheared BC)
IF (ikxBC_L .NE. -99) THEN
! Fill the lower ghosts cells with the buffer value (upper cells from LEFT process)
DO ig=1,ngz/2
moments(:,:,:,iky,ikx,first-ig,updatetlevel) = pb_phase_L(iky)*buff_pjxy_zBC(:,:,:,iky,ikxBC_L,-ig)
ENDDO
ELSE
DO ig=1,ngz/2
moments(:,:,:,iky,ikx,first-ig,updatetlevel) = 0._xp
ENDDO
ENDIF
ikxBC_R = ikx_zBC_R(iky,ikx);
! Exchanging the modes that have a periodic pair (from sheared BC)
IF (ikxBC_R .NE. -99) THEN
! Fill the upper ghosts cells with the buffer value (lower cells from RIGHT process)
DO ig=1,ngz/2
moments(:,:,:,iky,ikx,last+ig,updatetlevel) = pb_phase_R(iky)*buff_pjxy_zBC(:,:,:,iky,ikxBC_R,ig)
ENDDO
ELSE
DO ig=1,ngz/2
moments(:,:,:,iky,ikx,last+ig,updatetlevel) = 0._xp
ENDDO
ENDIF
ENDDO
ENDDO
END SUBROUTINE update_ghosts_z_mom
SUBROUTINE update_ghosts_z_3D(field)
USE geometry, ONLY: ikx_zBC_L, ikx_zBC_R, pb_phase_L, pb_phase_R
USE parallel, ONLY: nbr_U,nbr_D,comm0,num_procs_z
USE grid, ONLY: local_nky,local_nkx,local_nz,ngz
IMPLICIT NONE
!! buffer for data exchanges, the last dimension is indexing the z ghost cells
! Example in the full periodic case
! (down) |x|x|a|b|...|c|d|x|x| (UP) array along z with old ghost cells
! V
! |a|b|c|d| buffer
! 1 2 3 4 buffer indices
! V
! |c|d|a|b|...|c|d|a|b| array along z with update ghost cells
! 3 4 1 2 buffer indices
COMPLEX(xp),DIMENSION(local_nky,local_nkx,ngz) :: buff_xy_zBC
COMPLEX(xp), INTENT(INOUT) :: field(local_nky,local_nkx,local_nz+ngz)
INTEGER :: ikxBC_L, ikxBC_R, ikx, iky, first, last, ig, ierr
first = 1 + ngz/2
last = local_nz + ngz/2
count = local_nky * local_nkx
IF (num_procs_z .GT. 1) THEN
!!!!!!!!!!! Send ghost to up neighbour !!!!!!!!!!!!!!!!!!!!!!
DO ig = 1,ngz/2
CALL mpi_sendrecv( field(:,:,last-(ig-1)), count, mpi_xp_c, nbr_U, 30+ig, & ! Send to Up the last
buff_xy_zBC(:,:, ngz-(ig-1)), count, mpi_xp_c, nbr_D, 30+ig, & ! Receive from Down the first-1 (idx 3,4)
comm0, status, ierr)
ENDDO
!!!!!!!!!!! Send ghost to down neighbour !!!!!!!!!!!!!!!!!!!!!!
DO ig = 1,ngz/2
CALL mpi_sendrecv( field(:,:,first+(ig-1)), count, mpi_xp_c, nbr_D, 32+ig, & ! Send to Down the first
buff_xy_zBC(:,:,ig), count, mpi_xp_c, nbr_U, 32+ig, & ! Recieve from Up the last+1 (idx 1 2)
comm0, status, ierr)
ENDDO
ELSE
! no parallelization so just copy last cell into first ghosts and vice versa
DO ig = 1,ngz/2
buff_xy_zBC(:,:, ngz-(ig-1)) = field(:,:,last -(ig-1))
buff_xy_zBC(:,:, ig) = field(:,:,first+(ig-1))
ENDDO
ENDIF
DO iky = 1,local_nky
DO ikx = 1,local_nkx
ikxBC_L = ikx_zBC_L(iky,ikx)
IF (ikxBC_L .NE. -99) THEN ! Exchanging the modes that have a periodic pair (a)
DO ig = 1,ngz/2
field(iky,ikx,first-ig) = pb_phase_L(iky)*buff_xy_zBC(iky,ikxBC_L,ngz-(ig-1))
ENDDO
ELSE
DO ig = 1,ngz/2
field(iky,ikx,first-ig) = 0._xp
ENDDO
ENDIF
ikxBC_R = ikx_zBC_R(iky,ikx)
IF (ikxBC_R .NE. -99) THEN ! Exchanging the modes that have a periodic pair (a)
! last+1 gets first
DO ig = 1,ngz/2
field(iky,ikx,last+ig) = pb_phase_R(iky)*buff_xy_zBC(iky,ikxBC_R,ig)
ENDDO
ELSE
DO ig = 1,ngz/2
field(iky,ikx,last+ig) = 0._xp
ENDDO
ENDIF
ENDDO
ENDDO
END SUBROUTINE update_ghosts_z_3D
END MODULE ghosts