Constructs the redistribute mapping from a g_lo data decomposition to an e_lo decomposition
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(g_layout_type), | intent(in) | :: | g_lo | |||
type(e_layout_type), | intent(in) | :: | e_lo | |||
type(redist_type), | intent(inout) | :: | energy_map |
subroutine setup_energy_redistribute_local(g_lo, e_lo,energy_map)
use mp, only: nproc
use layouts_type, only: g_layout_type, e_layout_type
use gs2_layouts, only: ie_idx, ik_idx, it_idx, il_idx, is_idx, ig_idx, isign_idx
use gs2_layouts, only:proc_id, idx, idx_local
use redistribute, only: index_list_type, init_redist, delete_list
use sorting, only: quicksort
implicit none
type(g_layout_type), intent(in) :: g_lo
type(e_layout_type), intent(in) :: e_lo
type(redist_type), intent(in out) :: energy_map
type(index_list_type), dimension(0:nproc-1) :: to_list, from_list,sort_list
integer, dimension(0:nproc-1) :: nn_to, nn_from
integer, dimension(3) :: from_low, from_high
integer, dimension(2) :: to_high
integer :: to_low
integer :: ig, isign, iglo, ie, ielo
integer :: n, ip
!Initialise counters to zero
nn_to = 0
nn_from = 0
!First count how much data to send | g_lo-->e_lo
!Protect against procs with no data
if(g_lo%ulim_proc>=g_lo%llim_proc)then
do iglo = g_lo%llim_proc, g_lo%ulim_alloc
!Get e_lo idx for ig=-ntgrid and isign=1
ielo=idx(e_lo,-g_lo%ntgrid,1,ik_idx(g_lo,iglo), &
it_idx(g_lo,iglo),il_idx(g_lo,iglo),is_idx(g_lo,iglo))
!Loop over other local dimensions, noting that ig->ig+1 ==> ielo->ielo+1
do isign = 1,2
do ig=-g_lo%ntgrid, g_lo%ntgrid
!Increment the data sent counter for the processor with ielo
nn_from(proc_id(e_lo,ielo))=nn_from(proc_id(e_lo,ielo))+1
!Increment ielo
ielo=ielo+1
enddo
enddo
enddo
endif
!Now count how much data to receive | e_lo<--g_lo
!Protect against procs with no data
if(e_lo%ulim_proc>=e_lo%llim_proc)then
do ielo = e_lo%llim_proc, e_lo%ulim_alloc
do ie=1,g_lo%negrid !e_lo%?
!Get iglo
iglo=idx(g_lo,ik_idx(e_lo,ielo),it_idx(e_lo,ielo),&
il_idx(e_lo,ielo),ie,is_idx(e_lo,ielo))
!Increment the data to receive count for this proc
nn_to(proc_id(g_lo,iglo))=nn_to(proc_id(g_lo,iglo))+1
enddo
enddo
endif
!Now we've done counting allocate index arrays
do ip = 0, nproc-1
if (nn_from(ip) > 0) then
allocate (from_list(ip)%first(nn_from(ip)))
allocate (from_list(ip)%second(nn_from(ip)))
allocate (from_list(ip)%third(nn_from(ip)))
end if
if (nn_to(ip) > 0) then
allocate (to_list(ip)%first(nn_to(ip)))
allocate (to_list(ip)%second(nn_to(ip)))
!For sorting messages later
allocate (sort_list(ip)%first(nn_to(ip)))
end if
end do
!Reinitialise counters to zero
nn_to = 0
nn_from = 0
!First fill in the sending indices, these define the message order
!Protect against procs with no data
if(g_lo%ulim_proc>=g_lo%llim_proc)then
do iglo=g_lo%llim_proc,g_lo%ulim_alloc
!Convert to ielo for ig=-ntgrid and isign=1
ielo=idx(e_lo,-g_lo%ntgrid,1,ik_idx(g_lo,iglo), &
it_idx(g_lo,iglo),il_idx(g_lo,iglo),is_idx(g_lo,iglo))
!Loop over other local dimensions
do isign=1,2
do ig=-g_lo%ntgrid, g_lo%ntgrid
!Get proc id
ip=proc_id(e_lo,ielo)
!Increment procs message counter
n=nn_from(ip)+1
nn_from(ip)=n
!Store indices
from_list(ip)%first(n)=ig
from_list(ip)%second(n)=isign
from_list(ip)%third(n)=iglo
!Increment ielo
ielo=ielo+1
enddo
enddo
enddo
endif
!Now fill in receive indices, these must match message data order (achieved through sorting later)
!Protect against procs with no data
if(e_lo%ulim_proc>=e_lo%llim_proc)then
do ielo=e_lo%llim_proc,e_lo%ulim_alloc
!Get indices used for creating sort index
ig=ig_idx(e_lo,ielo)
isign=isign_idx(e_lo,ielo)
do ie=1,g_lo%negrid !e_lo%?
!Get iglo index
iglo=idx(g_lo,ik_idx(e_lo,ielo),it_idx(e_lo,ielo),&
il_idx(e_lo,ielo),ie,is_idx(e_lo,ielo))
!Get proc id
ip=proc_id(g_lo,iglo)
!Increment procs data counter
n=nn_to(ip)+1
nn_to(ip)=n
!Store message indices
to_list(ip)%first(n)=ie
to_list(ip)%second(n)=ielo
!Store index for sorting
sort_list(ip)%first(n)=ig+g_lo%ntgrid-1+g_lo%ntgridtotal*(isign-1+(iglo-g_lo%llim_world)*2)
enddo
enddo
endif
!Now sort receive indices into message order
do ip=0,nproc-1
!Only worry about cases where we're receiving data
if(nn_to(ip)>0) then
!Sort based on quicksort
call quicksort(nn_to(ip),sort_list(ip)%first,to_list(ip)%first,to_list(ip)%second)
endif
enddo
!Now setup array range values
from_low (1) = -g_lo%ntgrid
from_low (2) = 1
from_low (3) = g_lo%llim_proc
to_low = e_lo%llim_proc
to_high(1) = negrid+1 !e_lo%?
to_high(2) = e_lo%ulim_alloc
from_high(1) = g_lo%ntgrid
from_high(2) = 2
from_high(3) = g_lo%ulim_alloc
!Create energy map redistribute object
call init_redist (energy_map, 'c', to_low, to_high, to_list, &
from_low, from_high, from_list)
!Deallocate the list objects
call delete_list (to_list)
call delete_list (from_list)
call delete_list (sort_list)
end subroutine setup_energy_redistribute_local