Migrate the pre-regrid solution into this rank's old-element window, ready for a windowed ApplyTransferPlan. Call it BEFORE Regrid, which releases the storage the sends read:
call model%MigrateOldWindow(winFirst,winLast,wFirst,wLast,...)
call model%Regrid(newMesh,newGeom)
call model%ApplyTransferPlan(plan,interp,eFirst,eLast)
[wFirst,wLast] is this rank's window of GLOBAL old element indices, normalized so that wFirst > wLast means empty; winFirst/winLast are the same for every rank, which is what lets each end of a pair derive the shared schedule without communicating (see SELF_SolutionMigration). A rank with an empty window must still call this, because its peers may need old elements it owns.
This base implementation migrates into host memory, which on a GPU build means a device-to-host copy of the local field first; the GPU backend overrides it to assemble the window in device memory and receive into it directly.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(DGModel3D_t), | intent(inout) | :: | this | |||
| integer, | intent(in) | :: | winFirst(:) | (1:nRanks) window lower bounds, from PlanWindows |
||
| integer, | intent(in) | :: | winLast(:) | (1:nRanks) window upper bounds |
||
| integer, | intent(in) | :: | wFirst | this rank's window (wFirst > wLast if empty) |
||
| integer, | intent(in) | :: | wLast | |||
| integer(kind=int64), | intent(inout) | :: | nBytesRecv | |||
| integer(kind=int64), | intent(inout) | :: | nBytesSent | |||
| integer(kind=int64), | intent(inout) | :: | nElemRemote |
subroutine MigrateOldWindow_DGModel3D_t(this,winFirst,winLast,wFirst,wLast, &
nBytesRecv,nBytesSent,nElemRemote)
!! Migrate the pre-regrid solution into this rank's old-element window, ready for a windowed
!! ApplyTransferPlan. Call it BEFORE Regrid, which releases the storage the sends read:
!!
!! call model%MigrateOldWindow(winFirst,winLast,wFirst,wLast,...)
!! call model%Regrid(newMesh,newGeom)
!! call model%ApplyTransferPlan(plan,interp,eFirst,eLast)
!!
!! [wFirst,wLast] is this rank's window of GLOBAL old element indices, normalized so that
!! wFirst > wLast means empty; winFirst/winLast are the same for every rank, which is what
!! lets each end of a pair derive the shared schedule without communicating (see
!! SELF_SolutionMigration). A rank with an empty window must still call this, because its
!! peers may need old elements it owns.
!!
!! This base implementation migrates into host memory, which on a GPU build means a
!! device-to-host copy of the local field first; the GPU backend overrides it to assemble the
!! window in device memory and receive into it directly.
implicit none
class(DGModel3D_t),intent(inout) :: this
integer,intent(in) :: winFirst(:) !! (1:nRanks) window lower bounds, from PlanWindows
integer,intent(in) :: winLast(:) !! (1:nRanks) window upper bounds
integer,intent(in) :: wFirst !! this rank's window (wFirst > wLast if empty)
integer,intent(in) :: wLast
integer(int64),intent(inout) :: nBytesRecv
integer(int64),intent(inout) :: nBytesSent
integer(int64),intent(inout) :: nElemRemote
! Local
integer :: perElem,nWinElem,nWin
perElem = (this%solution%interp%N+1)*(this%solution%interp%N+1)*(this%solution%interp%N+1)
nWinElem = max(wLast-wFirst+1,0)
! Grow-only, and never zero-sized: a one-element floor keeps the actual argument below valid
! even for an empty window, which is the case for a rank that owns no new elements.
nWin = perElem*max(nWinElem,1)*this%nvar
if(allocated(this%winStage)) then
if(size(this%winStage) < nWin) deallocate(this%winStage)
endif
if(.not. allocated(this%winStage)) allocate(this%winStage(1:nWin))
call this%solution%UpdateHost()
call ExchangeOldWindowFlat(this%mesh%decomp,perElem,this%nvar,this%solution%nElem, &
this%solution%interior,winFirst,winLast,wFirst,wLast, &
this%winStage,nBytesRecv,nBytesSent,nElemRemote)
this%winStageFirst = wFirst
this%winStageN = nWinElem
endsubroutine MigrateOldWindow_DGModel3D_t