ApplyTransferPlan_DGModel2D_t Subroutine

public subroutine ApplyTransferPlan_DGModel2D_t(this, plan, interp, eFirst, eLast, uGlobal, oldFirst)

Transfer the staged pre-regrid solution onto the regridded mesh through plan, filling the rank-local element range [eFirst,eLast] of the new solution.

uGlobal is optional and supplies old-field data the caller has already assembled; when absent the locally staged copy from StageSolutionForTransfer is used, which is the whole field on a single rank. oldFirst is the global old element index of uGlobal's first element: absent (or 1) means uGlobal is the whole global old field (the Stage-5 v1 allgather path), while the point-to-point migration (v2) passes the window it received together with the window's first global old element index.

[eFirst,eLast] must be this rank's WHOLE new element range, so that eLast-eFirst+1 equals solution%nElem. The portable apply below writes uNew as an exactly-shaped array, so a sub-range of a larger field would place every variable after the first at the wrong stride; the device kernel is indifferent, because it is told the field's element stride separately. Do not rely on that difference - the contract is the whole range on both backends.

This base implementation runs the portable host transfer and uploads the result; the GPU backend overrides it to run the transfer on the device with no host traffic.

Arguments

TypeIntentOptionalAttributesName
class(DGModel2D_t), intent(inout), target:: this
type(TransferPlan2D), intent(in), target:: plan
type(Lagrange), intent(in) :: interp
integer, intent(in) :: eFirst
integer, intent(in) :: eLast
real(kind=prec), intent(in), optional contiguous:: uGlobal(:,:,:,:)
integer, intent(in), optional :: oldFirst

Calls

proc~~applytransferplan_dgmodel2d_t~~CallsGraph proc~applytransferplan_dgmodel2d_t ApplyTransferPlan_DGModel2D_t proc~applytransferplanwindow~2 ApplyTransferPlanWindow proc~applytransferplan_dgmodel2d_t->proc~applytransferplanwindow~2 proc~applytransferplanrange~2 ApplyTransferPlanRange proc~applytransferplan_dgmodel2d_t->proc~applytransferplanrange~2 proc~restrictfromchildren~2 RestrictFromChildren proc~applytransferplanwindow~2->proc~restrictfromchildren~2 proc~prolongtochildren~2 ProlongToChildren proc~applytransferplanwindow~2->proc~prolongtochildren~2 proc~applytransferplanrange~2->proc~applytransferplanwindow~2 tmp tmp proc~restrictfromchildren~2->tmp up up proc~restrictfromchildren~2->up proc~prolongtochildren~2->tmp

Called by

proc~~applytransferplan_dgmodel2d_t~~CalledByGraph proc~applytransferplan_dgmodel2d_t ApplyTransferPlan_DGModel2D_t proc~adapt_amrcontroller2d Adapt_AMRController2D proc~adapt_amrcontroller2d->proc~applytransferplan_dgmodel2d_t proc~applytransferplan_dgmodel2d ApplyTransferPlan_DGModel2D proc~applytransferplan_dgmodel2d->proc~applytransferplan_dgmodel2d_t

Contents


Source Code

  subroutine ApplyTransferPlan_DGModel2D_t(this,plan,interp,eFirst,eLast,uGlobal,oldFirst)
    !! Transfer the staged pre-regrid solution onto the regridded mesh through plan, filling the
    !! rank-local element range [eFirst,eLast] of the new solution.
    !!
    !! uGlobal is optional and supplies old-field data the caller has already assembled; when
    !! absent the locally staged copy from StageSolutionForTransfer is used, which is the whole
    !! field on a single rank. oldFirst is the global old element index of uGlobal's first
    !! element: absent (or 1) means uGlobal is the whole global old field (the Stage-5 v1
    !! allgather path), while the point-to-point migration (v2) passes the window it received
    !! together with the window's first global old element index.
    !!
    !! [eFirst,eLast] must be this rank's WHOLE new element range, so that eLast-eFirst+1 equals
    !! solution%nElem. The portable apply below writes uNew as an exactly-shaped array, so a
    !! sub-range of a larger field would place every variable after the first at the wrong stride;
    !! the device kernel is indifferent, because it is told the field's element stride separately.
    !! Do not rely on that difference - the contract is the whole range on both backends.
    !!
    !! This base implementation runs the portable host transfer and uploads the result; the GPU
    !! backend overrides it to run the transfer on the device with no host traffic.
    implicit none
    ! target on this: the migrated window is a flat component and the windowed apply is fed
    ! through a pointer remapped onto it (below), which requires the target attribute here.
    class(DGModel2D_t),intent(inout),target :: this
    ! target: the GPU override takes c_loc of the plan's arrays to upload them, which requires
    ! the POINTER or TARGET attribute. Declared here too so the override's characteristics match.
    type(TransferPlan2D),intent(in),target :: plan
    type(Lagrange),intent(in) :: interp
    integer,intent(in) :: eFirst
    integer,intent(in) :: eLast
    real(prec),intent(in),optional,contiguous :: uGlobal(:,:,:,:)
    integer,intent(in),optional :: oldFirst
    ! Local
    integer :: o1,o2,Np,perElem
    real(prec),pointer :: uWin(:,:,:,:)

    if(present(uGlobal)) then
      o1 = 1
      if(present(oldFirst)) o1 = oldFirst
      o2 = o1+size(uGlobal,3)-1
      call ApplyTransferPlanWindow(plan,interp,this%nvar,uGlobal,o1,o2,eFirst,eLast, &
                                   this%solution%interior)
    elseif(this%winStageN > 0) then
      if(allocated(this%transferStage)) then
        ! Two sources for one apply. The GPU override rejects the same combination; keeping the
        ! guard rails symmetric between the backends is the point, not the reachability - the
        ! controller never stages and migrates in the same epoch.
        print*,__FILE__,':',__LINE__, &
          ' : Error : ApplyTransferPlan has both a staged local field and a migrated window.'
        stop 1
      endif
      ! The multi-rank path: MigrateOldWindow left this rank's window of the old field in
      ! winStage. This is the same windowed apply as the uGlobal branch above, reading model
      ! state rather than a caller-supplied array, which is what lets the GPU backend hold the
      ! window in device memory and override only the migration and the apply.
      Np = interp%N+1
      perElem = Np*Np
      o1 = this%winStageFirst
      o2 = o1+this%winStageN-1
      uWin(1:Np,1:Np,o1:o2,1:this%nvar) => this%winStage(1:perElem*this%winStageN*this%nvar)
      call ApplyTransferPlanWindow(plan,interp,this%nvar,uWin,o1,o2,eFirst,eLast, &
                                   this%solution%interior)
      uWin => null()
    else
      if(.not. allocated(this%transferStage)) then
        print*,__FILE__,':',__LINE__, &
          ' : Error : ApplyTransferPlan called without a staged solution or a migrated window.'
        stop 1
      endif
      call ApplyTransferPlanRange(plan,interp,this%nvar,this%transferStage,eFirst,eLast, &
                                  this%solution%interior)
    endif

    call this%solution%UpdateDevice()

    if(allocated(this%transferStage)) deallocate(this%transferStage)
    ! The window buffer is retained (grow-only) but its marker is cleared, so a second apply
    ! without a fresh migration fails the guard rather than reusing a stale window.
    this%winStageN = 0

  endsubroutine ApplyTransferPlan_DGModel2D_t