fill_nwextra_device Subroutine

private subroutine fill_nwextra_device(igrid)

Uses

  • proc~~fill_nwextra_device~~UsesGraph proc~fill_nwextra_device fill_nwextra_device mod_usr mod_usr proc~fill_nwextra_device->mod_usr module~mod_global_parameters mod_global_parameters proc~fill_nwextra_device->module~mod_global_parameters module~mod_basic_types mod_basic_types module~mod_global_parameters->module~mod_basic_types module~mod_connectivity mod_connectivity module~mod_global_parameters->module~mod_connectivity module~mod_constants mod_constants module~mod_global_parameters->module~mod_constants module~mod_physicaldata mod_physicaldata module~mod_global_parameters->module~mod_physicaldata module~mod_variables mod_variables module~mod_global_parameters->module~mod_variables mpi mpi module~mod_global_parameters->mpi module~mod_variables->module~mod_basic_types

Fill this block's extra w-variables on the device from usr_set_nwextra.

The nwextra variables (registered by var_set_extravar) are not advected, carry no boundary condition, and here are taken to be analytic functions of position alone. Rather than exchange them through getbc or interpolate them in prolongation and coarsening - all of which stop at nwgc - they are re-derived from the user's usr_set_nwextra in every cell of every block, the full ixG range with ghost cells included. alloc_node is the sole caller: it runs for every block that comes into existence (a fresh root, a refined child, a coarsened parent, a load-balanced arrival), right after fill_geometry_device has written this block's positions, and nothing overwrites the extra slots afterwards.

Filling the ghost cells this way is also what lets a build with such a variable reach the polar axis: bgeo%x in the ghost layer beyond theta=0 (or r=0) carries the mirrored coordinate, so evaluating the user's analytic field there reproduces on its own the sign flips a vector picks up across the axis, with no entry in typeboundary and no pole branch in getbc.

This flag is set by config_schema.toml's implies for phys='ffhd', whose frozen field b1,b2,b3 is exactly such a variable.

Runs on the device: bgeo%x and bg(1)%w are both resident for all max_blocks from initialize_vars, so the kernel indexes them directly. mod_variables tracks nwextra and, via var_set_extravar, the w indices iw_extra(1:nwextra) the extra variables actually occupy - this routine makes no assumption about where in w they live.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: igrid

Calls

proc~~fill_nwextra_device~~CallsGraph proc~fill_nwextra_device fill_nwextra_device usr_set_nwextra usr_set_nwextra proc~fill_nwextra_device->usr_set_nwextra

Called by

proc~~fill_nwextra_device~~CalledByGraph proc~fill_nwextra_device fill_nwextra_device proc~alloc_node~4 alloc_node proc~alloc_node~4->proc~fill_nwextra_device

Source Code

  subroutine fill_nwextra_device(igrid)
    use mod_global_parameters
    use mod_usr, only: usr_set_nwextra

    integer, intent(in) :: igrid

    integer          :: ix1, ix2, ix3, iwx
    ! wx is sized by the compile-time max_nw, not the runtime nwextra: a
    ! variable-length private array in a GPU parallel loop is a fragile
    ! corner across OpenACC compilers. Only wx(1:nwextra) is passed and used.
    double precision :: xloc(1:ndim), wx(max_nw)

     
    do ix3 = ixGlo3, ixGhi3
       do ix2 = ixGlo2, ixGhi2
          do ix1 = ixGlo1, ixGhi1
             xloc(1:ndim) = bgeo%x(ix1,ix2,ix3,1:ndim,igrid)
             call usr_set_nwextra(xloc, wx(1:nwextra))
             do iwx = 1, nwextra
                bg(1)%w(ix1,ix2,ix3, iw_extra(iwx), igrid) = wx(iwx)
             end do
          end do
       end do
    end do

  end subroutine fill_nwextra_device