Register every configured tag against the shared reader and
resolve the heat/salt destinations. A no-op when
enable = .false. — nothing registers, so
ocean_data_input_update_all stays a no-op and the run is
bit-identical.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_dataovr_config_t), | intent(in) | :: | cfg | |||
| type(ocean_data_input_t), | intent(inout) | :: | reader | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_surface_stress_t), | intent(inout) | :: | ss | |||
| type(ocean_surface_flux_t), | intent(inout) | :: | sf | |||
| type(ocean_bc_state_t), | intent(in) | :: | bc |
Periodic / north-fold topology for the configure-time seam refresh. |
||
| type(ocean_data_forcing_t), | intent(out) | :: | this | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero ( |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | ng | ||||
| integer, | private | :: | nx | ||||
| integer, | private | :: | ny | ||||
| integer, | private | :: | oor |
subroutine ocean_data_forcing_configure(cfg, reader, grid, ss, sf, bc, this, ierr) !! Register every configured tag against the shared reader and !! resolve the heat/salt destinations. A no-op when !! `enable = .false.` — nothing registers, so !! `ocean_data_input_update_all` stays a no-op and the run is !! bit-identical. type(ocean_dataovr_config_t), intent(in) :: cfg type(ocean_data_input_t), intent(inout) :: reader type(hgrid_t), intent(in) :: grid type(ocean_surface_stress_t), intent(inout) :: ss type(ocean_surface_flux_t), intent(inout) :: sf type(ocean_bc_state_t), intent(in) :: bc !! Periodic / north-fold topology for the configure-time seam refresh. type(ocean_data_forcing_t), intent(out) :: this integer, intent(out), optional :: ierr !! Non-zero (`OCEAN_STATUS_ERR_SETUP`/`OCEAN_STATUS_ERR_IO`, see !! `rdb_ocean_status`) on a malformed `&ocean_dataovr_nml` group !! or a registration failure (bad file/variable/dims) when !! present; absent behaves as today (`error stop`). integer :: oor, nx, ny, ng if (present(ierr)) ierr = OCEAN_STATUS_OK if (.not. cfg%enable) return call check_time_mode(cfg, ierr=ierr) if (present(ierr)) then if (ierr /= OCEAN_STATUS_OK) return end if oor = DATA_OOR_ERROR if (cfg%oor_clamp) oor = DATA_OOR_CLAMP nx = grid%nx_total ny = grid%ny_total ng = grid%nghost ! --- wind stress: face-shaped destinations --- ! `tau_x` is (nx_total+1, ny_total) on east faces, `tau_y` is ! (nx_total, ny_total+1) on north faces, landing at (nghost+1, ! nghost+1). ! ! The file must supply nx_phys+1 x ny_phys values for `tau_x` ! (ny_phys+1 in y for `tau_y`) — one MORE than the cell count in ! the staggered direction. An x-face array spans nx_phys+1 faces, ! and the trailing face is owned by THIS rank under the ! west/south-owns-the-seam rule, so no exchange can fill it in. ! Supplying only nx_phys would silently leave that face at zero, ! which halves the cell-centred `stress_mag` in the last column ! and hands a zero to the east neighbour's seam. call register_tag(cfg, cfg%tau_x, "tau_x", reader, grid, oor, & nx + 1, ny, ng + 1, ng + 1, this%id_tau_x, nx_extra=1, ierr=ierr) if (present(ierr)) then if (ierr /= OCEAN_STATUS_OK) return end if call register_tag(cfg, cfg%tau_y, "tau_y", reader, grid, oor, & nx, ny + 1, ng + 1, ng + 1, this%id_tau_y, ny_extra=1, ierr=ierr) if (present(ierr)) then if (ierr /= OCEAN_STATUS_OK) return end if ! --- surface fluxes: cell-centred destinations --- call resolve_flux_targets(cfg, sf, this, ierr=ierr) if (present(ierr)) then if (ierr /= OCEAN_STATUS_OK) return end if call register_tag(cfg, cfg%heat, "heat", reader, grid, oor, & nx, ny, ng + 1, ng + 1, this%id_heat, ierr=ierr) if (present(ierr)) then if (ierr /= OCEAN_STATUS_OK) return end if call register_tag(cfg, cfg%evap, "evap", reader, grid, oor, & nx, ny, ng + 1, ng + 1, this%id_evap, ierr=ierr) if (present(ierr)) then if (ierr /= OCEAN_STATUS_OK) return end if call register_tag(cfg, cfg%lprec, "lprec", reader, grid, oor, & nx, ny, ng + 1, ng + 1, this%id_lprec, ierr=ierr) if (present(ierr)) then if (ierr /= OCEAN_STATUS_OK) return end if call register_tag(cfg, cfg%salt, "salt", reader, grid, oor, & nx, ny, ng + 1, ng + 1, this%id_salt, ierr=ierr) if (present(ierr)) then if (ierr /= OCEAN_STATUS_OK) return end if this%active = (this%id_tau_x > 0 .or. this%id_tau_y > 0 .or. & this%id_heat > 0 .or. this%id_evap > 0 .or. & this%id_lprec > 0 .or. this%id_salt > 0) if (.not. this%active) then call logger%warning("ocean_dataovr: enable = .true. but no tag has a file — "// & "every surface slot keeps its configure-time value") return end if ! Latches the consuming kernels gate on. Set HERE, not per step: ! they are host-side gates on a device-mapped derived type, and a ! host write to a mapped component never reaches the device. ! Registration is for the whole run, so the latch is too. if (this%id_heat > 0) sf%has_heat = .true. if (this%id_salt > 0) sf%has_salt = .true. if (this%id_evap > 0 .or. this%id_lprec > 0) sf%has_mass_flux = .true. ! `stress_mag` must be consistent with whatever the first blend ! writes; the first `apply` re-derives it, but configure-time ! consumers that read it before the first step should not see a ! value derived from a wind field that is about to be replaced. if (this%id_tau_x > 0 .or. this%id_tau_y > 0) then call ocean_seam_refresh_surface_stress(ss, grid, bc, device_resident=.false.) end if end subroutine ocean_data_forcing_configure