function rdb_ocean_set_tracer(c_handle, name, name_len, data, nx_p, ny_p, nz_p) &
result(status) bind(c, name="rdb_ocean_set_tracer")
!! Set the tracer named `name` to `data` (its own units — degC for
!! temperature, PSU for salinity) on the physical interior. Verbatim
!! the recovered `ocean_set_tracer_impl` sequence, generalised from
!! hardcoded S/T to any registered tracer BY NAME: flush the
!! windowed-advection accumulator -> refresh host (need the LIVE
!! `h_layer` to form `hTr = h_layer*value`) -> mutate `hTr` on the
!! physical interior -> narrow-push `hTr` -> recompute `rho_layer`
!! (pulled back to host so it stays authoritative).
!! `OCEAN_STATUS_ERR_NOT_FOUND` if no registered tracer matches.
type(c_ptr), intent(in), value :: c_handle
integer(c_int), intent(in), value :: name_len
character(kind=c_char), intent(in) :: name(name_len)
integer(c_int), intent(in), value :: nx_p, ny_p, nz_p
real(c_double), intent(in) :: data(nx_p, ny_p, nz_p)
integer(c_int) :: status
type(ocean_handle_t), pointer :: h
character(len=:), allocatable :: fname
integer :: ng, i, j, k, it, ierr_local
status = resolve_ocean(c_handle, h)
if (status /= OCEAN_STATUS_OK) return
if (.not. shape_matches_interior(h, nx_p, ny_p, nz_p)) then
call fail("rdb_ocean_set_tracer: shape mismatch against the physical interior", &
ierr_local, OCEAN_STATUS_ERR_BAD_SHAPE)
status = int(ierr_local, c_int)
return
end if
call c_to_f_string(name, name_len, fname)
it = tracer_index_by_name(h, fname)
if (it == 0) then
call fail("rdb_ocean_set_tracer: no tracer named '"//fname//"'", &
ierr_local, OCEAN_STATUS_ERR_NOT_FOUND)
status = int(ierr_local, c_int)
return
end if
! Drain any open windowed tracer-advection accumulation BEFORE
! reading/overwriting the tracer, so pending transport (accumulated
! against the OLD field) is never later applied to the NEW one.
! Hard no-op at dt_tracer_advect_ratio<=1 (default; bit-identical).
call ocean_dyn_flush_tracer_window(h%grid, h%state%metrics, h%state%dyn, &
h%state%continuity, h%state%multilayer, &
bc=h%state%bc)
call ocean_handle_refresh_host(h)
ng = h%grid%nghost
associate (hl => h%state%multilayer%h_layer, htr => h%state%multilayer%tracers(it)%hTr)
do k = 1, nz_p
do j = 1, ny_p
do i = 1, nx_p
htr(ng + i, ng + j, k) = hl(ng + i, ng + j, k)*real(data(i, j, k), wp)
end do
end do
end do
!$acc update device(htr)
end associate
call ocean_eos_compute(h%state%eos, h%state%multilayer)
associate (rl => h%state%multilayer%rho_layer)
!$acc update self(rl)
end associate
h%host_is_current = .true.
status = int(OCEAN_STATUS_OK, c_int)
end function rdb_ocean_set_tracer