For every rank r, the contiguous window [winFirst(r),winLast(r)] of GLOBAL old element indices that rank r's new element range references through the transfer plan. The plan is rank-replicated, so this is a purely local computation: no communication is needed to learn what a peer wants, which is what makes the point-to-point migration cheap here.
A rank owning no new elements gets the empty sentinel winFirst > winLast.
Correctness does not depend on the leaf ordering being monotone in the old ordering: the window is the min/max hull of the referenced indices, so a non-monotone ordering only widens it, the worst case being the whole old element list - i.e. exactly what the v1 gather-then-slice migration moves. Efficiency, not correctness, rests on the space-filling-curve locality.
Cost is ONE pass over the plan, not nRanks x nNew: the rank loop partitions 1..nNew.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(TransferPlan3D), | intent(in) | :: | plan | |||
| integer, | intent(in) | :: | nRanks | |||
| integer, | intent(in) | :: | newOffset(1:nRanks+1) | |||
| integer, | intent(out) | :: | winFirst(1:nRanks) | |||
| integer, | intent(out) | :: | winLast(1:nRanks) |
subroutine PlanWindows(plan,nRanks,newOffset,winFirst,winLast)
!! For every rank r, the contiguous window [winFirst(r),winLast(r)] of GLOBAL old element
!! indices that rank r's new element range references through the transfer plan. The plan is
!! rank-replicated, so this is a purely local computation: no communication is needed to
!! learn what a peer wants, which is what makes the point-to-point migration cheap here.
!!
!! A rank owning no new elements gets the empty sentinel winFirst > winLast.
!!
!! Correctness does not depend on the leaf ordering being monotone in the old ordering: the
!! window is the min/max hull of the referenced indices, so a non-monotone ordering only
!! widens it, the worst case being the whole old element list - i.e. exactly what the v1
!! gather-then-slice migration moves. Efficiency, not correctness, rests on the
!! space-filling-curve locality.
!!
!! Cost is ONE pass over the plan, not nRanks x nNew: the rank loop partitions 1..nNew.
implicit none
type(TransferPlan3D),intent(in) :: plan
integer,intent(in) :: nRanks
integer,intent(in) :: newOffset(1:nRanks+1)
integer,intent(out) :: winFirst(1:nRanks)
integer,intent(out) :: winLast(1:nRanks)
! Local
integer :: r,li,c,src
do r = 1,nRanks
winFirst(r) = plan%nOld+1
winLast(r) = 0
do li = newOffset(r)+1,newOffset(r+1)
if(plan%sourceKind(li) == SELF_TRANSFER_RESTRICT) then
do c = 1,8
src = plan%family(c,li)
winFirst(r) = min(winFirst(r),src)
winLast(r) = max(winLast(r),src)
enddo
else
src = plan%sourceElem(li)
winFirst(r) = min(winFirst(r),src)
winLast(r) = max(winLast(r),src)
endif
enddo
enddo
endsubroutine PlanWindows