Copy the migrated window into a host array, for the SELF_AMR_MIGRATE_VERIFY diagnostic. Diagnostic-only and off the default path: on a GPU build the override is a device-to-host transfer of the whole window, which is exactly the traffic the device path exists to avoid.
The comparison this feeds is BITWISE, and must stay that way. Migration is pure data movement - host and device copies, MPI byte transfers - so no arithmetic touches these values and exactness is available. That is unlike the transfer APPLY, which agrees between host and device only to round-off because the device compiler contracts its multiply-accumulates into FMAs. The two are checked by different switches for that reason.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(DGModel2D_t), | intent(in) | :: | this | |||
| integer, | intent(in) | :: | wFirst | |||
| integer, | intent(in) | :: | wLast | |||
| real(kind=prec), | intent(out), | target, contiguous | :: | uWin(:,:,:,:) | (Np,Np,nWinElem,nvar) |
subroutine DownloadOldWindow_DGModel2D_t(this,wFirst,wLast,uWin)
!! Copy the migrated window into a host array, for the SELF_AMR_MIGRATE_VERIFY diagnostic.
!! Diagnostic-only and off the default path: on a GPU build the override is a device-to-host
!! transfer of the whole window, which is exactly the traffic the device path exists to avoid.
!!
!! The comparison this feeds is BITWISE, and must stay that way. Migration is pure data
!! movement - host and device copies, MPI byte transfers - so no arithmetic touches these
!! values and exactness is available. That is unlike the transfer APPLY, which agrees between
!! host and device only to round-off because the device compiler contracts its
!! multiply-accumulates into FMAs. The two are checked by different switches for that reason.
implicit none
class(DGModel2D_t),intent(in) :: this
integer,intent(in) :: wFirst
integer,intent(in) :: wLast
! target: the GPU override takes c_loc of this to download the window in one memcpy.
real(prec),intent(out),target,contiguous :: uWin(:,:,:,:) !! (Np,Np,nWinElem,nvar)
! Local
integer :: Np,perElem,nWinElem,i,j,e,iv,p,off
nWinElem = max(wLast-wFirst+1,0)
if(nWinElem == 0) return
Np = this%solution%interp%N+1
perElem = Np*Np
if(size(uWin,3) /= nWinElem .or. size(uWin,4) /= this%nvar) then
print*,__FILE__,':',__LINE__, &
' : Error : DownloadOldWindow given a buffer that does not match the window.'
stop 1
endif
if(this%winStageN /= nWinElem .or. this%winStageFirst /= wFirst) then
print*,__FILE__,':',__LINE__, &
' : Error : DownloadOldWindow called without a matching migrated window.'
stop 1
endif
do iv = 1,this%nvar
do e = 1,nWinElem
off = perElem*((e-1)+nWinElem*(iv-1))
p = 0
do j = 1,Np
do i = 1,Np
p = p+1
uWin(i,j,e,iv) = this%winStage(off+p)
enddo
enddo
enddo
enddo
endsubroutine DownloadOldWindow_DGModel2D_t