rdb_ocean_diag_derived.F90 Source File

Library of derived ocean diagnostics — static catalog binding a diagnostic name to a fill procedure + CF-1.8 metadata, picked by name from the namelist. Every fill is a pure function of the current ocean_state_t; outputs at cell centres (vgrid LAYER, z-level remap via remap_layer_to_z). Includes the opt-in sea-ice drift diagnostics (ice_speed/ice_u/ice_v) — the canonical ice_conc/ice_thick fills live in rdb_ocean_diag_fills (module- cycle rule: this module USES that one).


This file depends on

sourcefile~~rdb_ocean_diag_derived.f90~~EfferentGraph sourcefile~rdb_ocean_diag_derived.f90 rdb_ocean_diag_derived.F90 sourcefile~rdb_constants.f90 rdb_constants.F90 sourcefile~rdb_ocean_diag_derived.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_eos.f90 rdb_eos.F90 sourcefile~rdb_ocean_diag_derived.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_error_ring.f90 rdb_error_ring.F90 sourcefile~rdb_ocean_diag_derived.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_diag.f90 rdb_ocean_diag.F90 sourcefile~rdb_ocean_diag_derived.f90->sourcefile~rdb_ocean_diag.f90 sourcefile~rdb_ocean_diag_fills.f90 rdb_ocean_diag_fills.F90 sourcefile~rdb_ocean_diag_derived.f90->sourcefile~rdb_ocean_diag_fills.f90 sourcefile~rdb_ocean_state.f90 rdb_ocean_state.F90 sourcefile~rdb_ocean_diag_derived.f90->sourcefile~rdb_ocean_state.f90 sourcefile~rdb_eos.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_eos.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_grid.f90 rdb_grid.F90 sourcefile~rdb_eos.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_status.f90 rdb_ocean_status.F90 sourcefile~rdb_eos.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_diag.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_diag.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_diag.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_mem_report.f90 rdb_mem_report.F90 sourcefile~rdb_ocean_diag.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_diag_mask.f90 rdb_ocean_diag_mask.F90 sourcefile~rdb_ocean_diag.f90->sourcefile~rdb_ocean_diag_mask.f90 sourcefile~rdb_ocean_diag.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_diag_fills.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_diag_fills.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_diag_fills.f90->sourcefile~rdb_ocean_diag.f90 sourcefile~rdb_ocean_diag_fills.f90->sourcefile~rdb_ocean_state.f90 sourcefile~rdb_ice_column.f90 rdb_ice_column.F90 sourcefile~rdb_ocean_diag_fills.f90->sourcefile~rdb_ice_column.f90 sourcefile~rdb_ocean_pseudo_salt.f90 rdb_ocean_pseudo_salt.F90 sourcefile~rdb_ocean_diag_fills.f90->sourcefile~rdb_ocean_pseudo_salt.f90 sourcefile~rdb_ocean_vcoord.f90 rdb_ocean_vcoord.F90 sourcefile~rdb_ocean_diag_fills.f90->sourcefile~rdb_ocean_vcoord.f90 sourcefile~rdb_remap_column.f90 rdb_remap_column.F90 sourcefile~rdb_ocean_diag_fills.f90->sourcefile~rdb_remap_column.f90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_diag.f90 sourcefile~rdb_barotropic_state.f90 rdb_barotropic_state.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_barotropic_state.f90 sourcefile~rdb_bathymetry.f90 rdb_bathymetry.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_bathymetry.f90 sourcefile~rdb_comm_env.f90 rdb_comm_env.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_comm_env.f90 sourcefile~rdb_config.f90 rdb_config.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_config.f90 sourcefile~rdb_continuity.f90 rdb_continuity.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_continuity.f90 sourcefile~rdb_coriolis_adv.f90 rdb_coriolis_adv.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_coriolis_adv.f90 sourcefile~rdb_decomp.f90 rdb_decomp.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_decomp.f90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ice_state.f90 rdb_ice_state.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ice_state.f90 sourcefile~rdb_multilayer_state.f90 rdb_multilayer_state.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_bathymetry_inject.f90 rdb_ocean_bathymetry_inject.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_bathymetry_inject.f90 sourcefile~rdb_ocean_bottom_drag.f90 rdb_ocean_bottom_drag.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_bottom_drag.f90 sourcefile~rdb_ocean_boundary_types.f90 rdb_ocean_boundary_types.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_cavity.f90 rdb_ocean_cavity.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_cavity.f90 sourcefile~rdb_ocean_cavity_flux.f90 rdb_ocean_cavity_flux.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_cavity_flux.f90 sourcefile~rdb_ocean_data_forcing.f90 rdb_ocean_data_forcing.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_data_forcing.f90 sourcefile~rdb_ocean_data_input.f90 rdb_ocean_data_input.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_data_input.f90 sourcefile~rdb_ocean_dyn.f90 rdb_ocean_dyn.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_dyn.f90 sourcefile~rdb_ocean_epbl.f90 rdb_ocean_epbl.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_epbl.f90 sourcefile~rdb_ocean_fold.f90 rdb_ocean_fold.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_fold.f90 sourcefile~rdb_ocean_gm.f90 rdb_ocean_gm.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_gm.f90 sourcefile~rdb_ocean_hdiff_tracer.f90 rdb_ocean_hdiff_tracer.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_hdiff_tracer.f90 sourcefile~rdb_ocean_horizontal_viscosity.f90 rdb_ocean_horizontal_viscosity.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_horizontal_viscosity.f90 sourcefile~rdb_ocean_isopycnal_slopes.f90 rdb_ocean_isopycnal_slopes.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_isopycnal_slopes.f90 sourcefile~rdb_ocean_kappa_shear.f90 rdb_ocean_kappa_shear.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_kappa_shear.f90 sourcefile~rdb_ocean_lateral_mix.f90 rdb_ocean_lateral_mix.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_lateral_mix.f90 sourcefile~rdb_ocean_meke.f90 rdb_ocean_meke.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_meke.f90 sourcefile~rdb_ocean_metrics.f90 rdb_ocean_metrics.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_mle.f90 rdb_ocean_mle.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_mle.f90 sourcefile~rdb_ocean_obc.f90 rdb_ocean_obc.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_obc.f90 sourcefile~rdb_ocean_p_surf.f90 rdb_ocean_p_surf.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_p_surf.f90 sourcefile~rdb_ocean_periodic.f90 rdb_ocean_periodic.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_periodic.f90 sourcefile~rdb_ocean_pressure_force.f90 rdb_ocean_pressure_force.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_pressure_force.f90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_pseudo_salt.f90 sourcefile~rdb_ocean_redi.f90 rdb_ocean_redi.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_redi.f90 sourcefile~rdb_ocean_restart.f90 rdb_ocean_restart.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_restart.f90 sourcefile~rdb_ocean_restart_io.f90 rdb_ocean_restart_io.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_restart_io.f90 sourcefile~rdb_ocean_sponge.f90 rdb_ocean_sponge.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_sponge.f90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_surface_flux.f90 rdb_ocean_surface_flux.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_surface_flux.f90 sourcefile~rdb_ocean_surface_stress.f90 rdb_ocean_surface_stress.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_surface_stress.f90 sourcefile~rdb_ocean_tidal_mixing.f90 rdb_ocean_tidal_mixing.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_tidal_mixing.f90 sourcefile~rdb_ocean_tides.f90 rdb_ocean_tides.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_tides.f90 sourcefile~rdb_ocean_top_drag.f90 rdb_ocean_top_drag.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_top_drag.f90 sourcefile~rdb_ocean_varmix.f90 rdb_ocean_varmix.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_varmix.f90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_vcoord.f90 sourcefile~rdb_ocean_vdiff.f90 rdb_ocean_vdiff.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_vdiff.f90 sourcefile~rdb_ocean_vertical_advection.f90 rdb_ocean_vertical_advection.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_vertical_advection.f90 sourcefile~rdb_ocean_vmix.f90 rdb_ocean_vmix.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_vmix.f90 sourcefile~rdb_ocean_wave_speed.f90 rdb_ocean_wave_speed.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_wave_speed.f90 sourcefile~rdb_ocean_z_init.f90 rdb_ocean_z_init.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_z_init.f90 sourcefile~rdb_profiler.f90 rdb_profiler.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_profiler.f90 sourcefile~rdb_barotropic_state.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_barotropic_state.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_barotropic_state.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_bathymetry.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_bathymetry.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_bathymetry.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_io_netcdf.f90 rdb_io_netcdf.F90 sourcefile~rdb_bathymetry.f90->sourcefile~rdb_io_netcdf.f90 sourcefile~rdb_comm_env.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_config.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_config.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_config.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_config.f90->sourcefile~rdb_coriolis_adv.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_bottom_drag.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_cavity.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_horizontal_viscosity.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_lateral_mix.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_pressure_force.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_pseudo_salt.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_surface_flux.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_tidal_mixing.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_top_drag.f90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_vmix.f90 sourcefile~rdb_ice_enthalpy.f90 rdb_ice_enthalpy.F90 sourcefile~rdb_config.f90->sourcefile~rdb_ice_enthalpy.f90 sourcefile~rdb_ice_init.f90 rdb_ice_init.F90 sourcefile~rdb_config.f90->sourcefile~rdb_ice_init.f90 sourcefile~rdb_nml_schema.f90 rdb_nml_schema.F90 sourcefile~rdb_config.f90->sourcefile~rdb_nml_schema.f90 sourcefile~rdb_ocean_cavity_melt.f90 rdb_ocean_cavity_melt.F90 sourcefile~rdb_config.f90->sourcefile~rdb_ocean_cavity_melt.f90 sourcefile~rdb_recon_weno.f90 rdb_recon_weno.F90 sourcefile~rdb_config.f90->sourcefile~rdb_recon_weno.f90 sourcefile~rdb_vcoord.f90 rdb_vcoord.F90 sourcefile~rdb_config.f90->sourcefile~rdb_vcoord.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_barotropic_state.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_ocean_fold.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_ocean_gm.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_ocean_mle.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_ocean_periodic.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_profiler.f90 sourcefile~rdb_ocean_fold_apply.f90 rdb_ocean_fold_apply.F90 sourcefile~rdb_continuity.f90->sourcefile~rdb_ocean_fold_apply.f90 sourcefile~rdb_ocean_fold_exchange.f90 rdb_ocean_fold_exchange.F90 sourcefile~rdb_continuity.f90->sourcefile~rdb_ocean_fold_exchange.f90 sourcefile~rdb_ocean_halo.f90 rdb_ocean_halo.F90 sourcefile~rdb_continuity.f90->sourcefile~rdb_ocean_halo.f90 sourcefile~rdb_continuity.f90->sourcefile~rdb_recon_weno.f90 sourcefile~rdb_scratch_3d.f90 rdb_scratch_3d.F90 sourcefile~rdb_continuity.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_tracer.f90 rdb_tracer.F90 sourcefile~rdb_continuity.f90->sourcefile~rdb_tracer.f90 sourcefile~rdb_coriolis_adv.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_coriolis_adv.f90->sourcefile~rdb_barotropic_state.f90 sourcefile~rdb_coriolis_adv.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_coriolis_adv.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_coriolis_adv.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_coriolis_adv.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_porous.f90 rdb_ocean_porous.F90 sourcefile~rdb_coriolis_adv.f90->sourcefile~rdb_ocean_porous.f90 sourcefile~rdb_coriolis_adv.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_decomp.f90->sourcefile~rdb_config.f90 sourcefile~rdb_grid.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ice_column.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ice_column.f90->sourcefile~rdb_ice_enthalpy.f90 sourcefile~rdb_ice_mass.f90 rdb_ice_mass.F90 sourcefile~rdb_ice_column.f90->sourcefile~rdb_ice_mass.f90 sourcefile~rdb_ice_optics.f90 rdb_ice_optics.F90 sourcefile~rdb_ice_column.f90->sourcefile~rdb_ice_optics.f90 sourcefile~rdb_ice_state.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ice_state.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ice_state.f90->sourcefile~rdb_ice_column.f90 sourcefile~rdb_ice_state.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ice_state.f90->sourcefile~rdb_ice_enthalpy.f90 sourcefile~rdb_mem_report.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_multilayer_state.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_multilayer_state.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_multilayer_state.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_multilayer_state.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_efp.f90 rdb_efp.F90 sourcefile~rdb_multilayer_state.f90->sourcefile~rdb_efp.f90 sourcefile~rdb_multilayer_state.f90->sourcefile~rdb_tracer.f90 sourcefile~rdb_ocean_bathymetry_inject.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_bathymetry_inject.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_bathymetry_inject.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_bathymetry_inject.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_bottom_drag.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_bottom_drag.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_bottom_drag.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_bottom_drag.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_bottom_drag.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_bottom_drag.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_ocean_boundary_types.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_boundary_types.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_boundary_types.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_boundary_types.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_tide_astro.f90 rdb_ocean_tide_astro.F90 sourcefile~rdb_ocean_boundary_types.f90->sourcefile~rdb_ocean_tide_astro.f90 sourcefile~rdb_ocean_cavity.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_cavity.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_cavity_flux.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_cavity_flux.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_cavity_flux.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_cavity_flux.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_cavity_flux.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_cavity_flux.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_cavity_flux.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_cavity_flux.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_cavity_flux.f90->sourcefile~rdb_ocean_surface_flux.f90 sourcefile~rdb_halo.f90 rdb_halo.F90 sourcefile~rdb_ocean_cavity_flux.f90->sourcefile~rdb_halo.f90 sourcefile~rdb_ocean_cavity_flux.f90->sourcefile~rdb_ocean_cavity_melt.f90 sourcefile~rdb_ocean_data_forcing.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_data_forcing.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_data_forcing.f90->sourcefile~rdb_config.f90 sourcefile~rdb_ocean_data_forcing.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_data_forcing.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_data_forcing.f90->sourcefile~rdb_ocean_data_input.f90 sourcefile~rdb_ocean_data_forcing.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_data_forcing.f90->sourcefile~rdb_ocean_surface_flux.f90 sourcefile~rdb_ocean_data_forcing.f90->sourcefile~rdb_ocean_surface_stress.f90 sourcefile~rdb_ocean_halo_state.f90 rdb_ocean_halo_state.F90 sourcefile~rdb_ocean_data_forcing.f90->sourcefile~rdb_ocean_halo_state.f90 sourcefile~rdb_ocean_data_input.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_data_input.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_data_input.f90->sourcefile~rdb_config.f90 sourcefile~rdb_ocean_data_input.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_data_input.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_data_input.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_data_input.f90->sourcefile~rdb_io_netcdf.f90 sourcefile~rdb_ocean_diag_mask.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_diag_mask.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_diag_mask.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_barotropic_state.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_continuity.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_coriolis_adv.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_bottom_drag.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_cavity_flux.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_epbl.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_gm.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_hdiff_tracer.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_horizontal_viscosity.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_isopycnal_slopes.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_kappa_shear.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_lateral_mix.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_meke.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_mle.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_p_surf.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_periodic.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_pressure_force.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_redi.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_sponge.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_surface_flux.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_surface_stress.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_tidal_mixing.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_tides.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_top_drag.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_varmix.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_vcoord.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_vdiff.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_vertical_advection.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_vmix.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_wave_speed.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_profiler.f90 sourcefile~rdb_barotropic_coupling.f90 rdb_barotropic_coupling.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_barotropic_coupling.f90 sourcefile~rdb_barotropic_substep.f90 rdb_barotropic_substep.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_barotropic_substep.f90 sourcefile~rdb_barotropic_workstate.f90 rdb_barotropic_workstate.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_barotropic_workstate.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_efp.f90 sourcefile~rdb_ocean_bt_budget_probe.f90 rdb_ocean_bt_budget_probe.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_bt_budget_probe.f90 sourcefile~rdb_ocean_bt_wide.f90 rdb_ocean_bt_wide.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_bt_wide.f90 sourcefile~rdb_ocean_chksum.f90 rdb_ocean_chksum.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_chksum.f90 sourcefile~rdb_ocean_console_stats.f90 rdb_ocean_console_stats.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_console_stats.f90 sourcefile~rdb_ocean_eos_compute.f90 rdb_ocean_eos_compute.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_eos_compute.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_fold_apply.f90 sourcefile~rdb_ocean_geothermal.f90 rdb_ocean_geothermal.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_geothermal.f90 sourcefile~rdb_ocean_ghost_poison.f90 rdb_ocean_ghost_poison.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_ghost_poison.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_halo.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_halo_state.f90 sourcefile~rdb_ocean_ideal_age.f90 rdb_ocean_ideal_age.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_ideal_age.f90 sourcefile~rdb_ocean_ke_probe.f90 rdb_ocean_ke_probe.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_ke_probe.f90 sourcefile~rdb_ocean_min_thickness.f90 rdb_ocean_min_thickness.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_min_thickness.f90 sourcefile~rdb_ocean_obc_baroclinic.f90 rdb_ocean_obc_baroclinic.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_obc_baroclinic.f90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_porous.f90 sourcefile~rdb_ocean_remap.f90 rdb_ocean_remap.F90 sourcefile~rdb_ocean_dyn.f90->sourcefile~rdb_ocean_remap.f90 sourcefile~rdb_ocean_epbl.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_epbl.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_epbl.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_epbl.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_epbl.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_epbl.f90->sourcefile~rdb_ocean_surface_flux.f90 sourcefile~rdb_ocean_epbl.f90->sourcefile~rdb_ocean_surface_stress.f90 sourcefile~rdb_ocean_epbl.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_ocean_fold.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_gm.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_gm.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_gm.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_gm.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_gm.f90->sourcefile~rdb_ocean_isopycnal_slopes.f90 sourcefile~rdb_ocean_gm.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_hdiff_tracer.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_hdiff_tracer.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_hdiff_tracer.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_hdiff_tracer.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_hdiff_tracer.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_hdiff_tracer.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_hdiff_tracer.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_ocean_hdiff_tracer.f90->sourcefile~rdb_tracer.f90 sourcefile~rdb_ocean_horizontal_viscosity.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_horizontal_viscosity.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_horizontal_viscosity.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_horizontal_viscosity.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_horizontal_viscosity.f90->sourcefile~rdb_ocean_lateral_mix.f90 sourcefile~rdb_ocean_horizontal_viscosity.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_horizontal_viscosity.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_ocean_isopycnal_slopes.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_isopycnal_slopes.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_isopycnal_slopes.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_isopycnal_slopes.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_isopycnal_slopes.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_isopycnal_slopes.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_kappa_shear.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_kappa_shear.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_kappa_shear.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_kappa_shear.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_kappa_shear.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_massless.f90 rdb_massless.F90 sourcefile~rdb_ocean_kappa_shear.f90->sourcefile~rdb_massless.f90 sourcefile~rdb_ocean_lateral_mix.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_lateral_mix.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_lateral_mix.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_lateral_mix.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_lateral_mix.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_lateral_mix.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_ocean_meke.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_meke.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_meke.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_meke.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_meke.f90->sourcefile~rdb_ocean_gm.f90 sourcefile~rdb_ocean_meke.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_meke.f90->sourcefile~rdb_ocean_varmix.f90 sourcefile~rdb_ocean_meke.f90->sourcefile~rdb_ocean_wave_speed.f90 sourcefile~rdb_ocean_metrics.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_metrics.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_metrics.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_metrics.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_metrics.f90->sourcefile~rdb_ocean_fold.f90 sourcefile~rdb_ocean_metrics.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_metrics.f90->sourcefile~rdb_io_netcdf.f90 sourcefile~rdb_ocean_bipolar.f90 rdb_ocean_bipolar.F90 sourcefile~rdb_ocean_metrics.f90->sourcefile~rdb_ocean_bipolar.f90 sourcefile~rdb_ocean_mle.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_mle.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_mle.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_mle.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_mle.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_mle.f90->sourcefile~rdb_ocean_epbl.f90 sourcefile~rdb_ocean_mle.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_mle.f90->sourcefile~rdb_ocean_surface_stress.f90 sourcefile~rdb_ocean_obc.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_obc.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_obc.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_p_surf.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_p_surf.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_p_surf.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_periodic.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_periodic.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_periodic.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_periodic.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_pressure_force.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_pressure_force.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_pressure_force.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_pressure_force.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_pressure_force.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_pressure_force.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_pgf_reconstruct.f90 rdb_ocean_pgf_reconstruct.F90 sourcefile~rdb_ocean_pressure_force.f90->sourcefile~rdb_ocean_pgf_reconstruct.f90 sourcefile~rdb_ocean_pressure_force.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_ocean_pseudo_salt.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_pseudo_salt.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_pseudo_salt.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_pseudo_salt.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_redi.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_redi.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_redi.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_redi.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_redi.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_redi.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_redi.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_redi.f90->sourcefile~rdb_tracer.f90 sourcefile~rdb_ocean_restart.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_restart_io.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_restart_io.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_restart_io.f90->sourcefile~rdb_decomp.f90 sourcefile~rdb_ocean_restart_io.f90->sourcefile~rdb_ocean_restart.f90 sourcefile~rdb_ocean_restart_io.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_restart_io.f90->sourcefile~rdb_io_netcdf.f90 sourcefile~rdb_ocean_sponge.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_sponge.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_sponge.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_sponge.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_sponge.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_surface_flux.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_surface_flux.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_surface_flux.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_surface_flux.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_surface_stress.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_surface_stress.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_surface_stress.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_surface_stress.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_surface_stress.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_ocean_tidal_mixing.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_tidal_mixing.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_tidal_mixing.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_tidal_mixing.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_tidal_mixing.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_tides.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_tides.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_tides.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_tides.f90->sourcefile~rdb_ocean_tide_astro.f90 sourcefile~rdb_ocean_top_drag.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_top_drag.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_top_drag.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_top_drag.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_top_drag.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_ocean_varmix.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_varmix.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_varmix.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_varmix.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_varmix.f90->sourcefile~rdb_ocean_isopycnal_slopes.f90 sourcefile~rdb_ocean_varmix.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_varmix.f90->sourcefile~rdb_ocean_wave_speed.f90 sourcefile~rdb_ocean_vcoord.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_vcoord.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_vcoord.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_vcoord.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_vcoord.f90->sourcefile~rdb_vcoord.f90 sourcefile~rdb_ocean_vdiff.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_vdiff.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_vdiff.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_vdiff.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_vdiff.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_vdiff.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_ocean_vdiff.f90->sourcefile~rdb_tracer.f90 sourcefile~rdb_ocean_vertical_advection.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_vertical_advection.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_vertical_advection.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_vertical_advection.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_vertical_advection.f90->sourcefile~rdb_scratch_3d.f90 sourcefile~rdb_ocean_vertical_advection.f90->sourcefile~rdb_tracer.f90 sourcefile~rdb_ocean_vmix.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_vmix.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_vmix.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_vmix.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_vmix.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_vmix.f90->sourcefile~rdb_ocean_surface_flux.f90 sourcefile~rdb_ocean_vmix.f90->sourcefile~rdb_ocean_surface_stress.f90 sourcefile~rdb_ocean_wave_speed.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_wave_speed.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_wave_speed.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_wave_speed.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_wave_speed.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_z_init.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_z_init.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_z_init.f90->sourcefile~rdb_config.f90 sourcefile~rdb_ocean_z_init.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_z_init.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_z_init.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_z_init.f90->sourcefile~rdb_io_netcdf.f90 sourcefile~rdb_remap_column.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_coriolis_adv.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_ocean_bottom_drag.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_ocean_horizontal_viscosity.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_ocean_pressure_force.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_ocean_surface_stress.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_ocean_top_drag.f90 sourcefile~rdb_barotropic_coupling.f90->sourcefile~rdb_barotropic_workstate.f90 sourcefile~rdb_barotropic_substep.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_barotropic_substep.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_barotropic_substep.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_barotropic_substep.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_barotropic_substep.f90->sourcefile~rdb_profiler.f90 sourcefile~rdb_barotropic_substep.f90->sourcefile~rdb_barotropic_workstate.f90 sourcefile~rdb_barotropic_substep.f90->sourcefile~rdb_ocean_fold_exchange.f90 sourcefile~rdb_barotropic_substep.f90->sourcefile~rdb_ocean_halo.f90 sourcefile~rdb_bt_cont_type.f90 rdb_bt_cont_type.F90 sourcefile~rdb_barotropic_substep.f90->sourcefile~rdb_bt_cont_type.f90 sourcefile~rdb_ocean_halo_counters.f90 rdb_ocean_halo_counters.F90 sourcefile~rdb_barotropic_substep.f90->sourcefile~rdb_ocean_halo_counters.f90 sourcefile~rdb_barotropic_workstate.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_barotropic_workstate.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_barotropic_workstate.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_halo.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_halo.f90->sourcefile~rdb_comm_env.f90 sourcefile~rdb_halo.f90->sourcefile~rdb_decomp.f90 sourcefile~rdb_halo.f90->sourcefile~rdb_efp.f90 sourcefile~rdb_ice_enthalpy.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ice_init.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ice_init.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ice_init.f90->sourcefile~rdb_ice_column.f90 sourcefile~rdb_ice_init.f90->sourcefile~rdb_ice_state.f90 sourcefile~rdb_ice_init.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ice_init.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ice_init.f90->sourcefile~rdb_ice_enthalpy.f90 sourcefile~rdb_ice_mass.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ice_mass.f90->sourcefile~rdb_ice_enthalpy.f90 sourcefile~rdb_ice_optics.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ice_optics.f90->sourcefile~rdb_ice_enthalpy.f90 sourcefile~rdb_io_netcdf.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_io_netcdf.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_massless.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_nml_schema.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_nml_schema.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_bipolar.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_bt_budget_probe.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_bt_budget_probe.f90->sourcefile~rdb_coriolis_adv.f90 sourcefile~rdb_ocean_bt_budget_probe.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_bt_budget_probe.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_bt_budget_probe.f90->sourcefile~rdb_ocean_bottom_drag.f90 sourcefile~rdb_ocean_bt_budget_probe.f90->sourcefile~rdb_ocean_horizontal_viscosity.f90 sourcefile~rdb_ocean_bt_budget_probe.f90->sourcefile~rdb_ocean_pressure_force.f90 sourcefile~rdb_ocean_bt_budget_probe.f90->sourcefile~rdb_ocean_surface_stress.f90 sourcefile~rdb_ocean_bt_budget_probe.f90->sourcefile~rdb_barotropic_workstate.f90 sourcefile~rdb_ocean_bt_wide.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_bt_wide.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_bt_wide.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_ocean_bt_wide.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_bt_wide.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_bt_wide.f90->sourcefile~rdb_profiler.f90 sourcefile~rdb_ocean_bt_wide.f90->sourcefile~rdb_barotropic_substep.f90 sourcefile~rdb_ocean_bt_wide.f90->sourcefile~rdb_barotropic_workstate.f90 sourcefile~rdb_ocean_bt_wide.f90->sourcefile~rdb_ocean_halo.f90 sourcefile~rdb_ocean_cavity_melt.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_cavity_melt.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_chksum.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_chksum.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_chksum.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_chksum.f90->sourcefile~rdb_barotropic_workstate.f90 sourcefile~rdb_ocean_chksum.f90->sourcefile~rdb_halo.f90 sourcefile~rdb_ocean_console_stats.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_console_stats.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_console_stats.f90->sourcefile~rdb_ice_column.f90 sourcefile~rdb_ocean_console_stats.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_console_stats.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_console_stats.f90->sourcefile~rdb_efp.f90 sourcefile~rdb_ocean_console_stats.f90->sourcefile~rdb_halo.f90 sourcefile~rdb_console_stats.f90 rdb_console_stats.F90 sourcefile~rdb_ocean_console_stats.f90->sourcefile~rdb_console_stats.f90 sourcefile~rdb_ocean_console_stats.f90->sourcefile~rdb_ocean_halo_counters.f90 sourcefile~rdb_ocean_eos_compute.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_eos_compute.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_fold_apply.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_fold_apply.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_fold_apply.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_fold_apply.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_fold_apply.f90->sourcefile~rdb_ocean_fold.f90 sourcefile~rdb_ocean_fold_apply.f90->sourcefile~rdb_ocean_fold_exchange.f90 sourcefile~rdb_ocean_fold_exchange.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_fold_exchange.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_fold_exchange.f90->sourcefile~rdb_comm_env.f90 sourcefile~rdb_ocean_fold_exchange.f90->sourcefile~rdb_decomp.f90 sourcefile~rdb_ocean_fold_exchange.f90->sourcefile~rdb_ocean_fold.f90 sourcefile~rdb_ocean_fold_exchange.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_fold_plan.f90 rdb_ocean_fold_plan.F90 sourcefile~rdb_ocean_fold_exchange.f90->sourcefile~rdb_ocean_fold_plan.f90 sourcefile~rdb_ocean_geothermal.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_geothermal.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_geothermal.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_geothermal.f90->sourcefile~rdb_ocean_surface_flux.f90 sourcefile~rdb_ocean_ghost_poison.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_ghost_poison.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_ghost_poison.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_ghost_poison.f90->sourcefile~rdb_ocean_surface_stress.f90 sourcefile~rdb_ocean_ghost_poison.f90->sourcefile~rdb_barotropic_workstate.f90 sourcefile~rdb_ocean_halo.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_halo.f90->sourcefile~rdb_error_ring.f90 sourcefile~rdb_ocean_halo.f90->sourcefile~rdb_comm_env.f90 sourcefile~rdb_ocean_halo.f90->sourcefile~rdb_decomp.f90 sourcefile~rdb_ocean_halo.f90->sourcefile~rdb_ocean_periodic.f90 sourcefile~rdb_ocean_halo.f90->sourcefile~rdb_ocean_status.f90 sourcefile~rdb_ocean_halo.f90->sourcefile~rdb_ocean_halo_counters.f90 sourcefile~rdb_ocean_halo_state.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_halo_state.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_halo_state.f90->sourcefile~rdb_ice_state.f90 sourcefile~rdb_ocean_halo_state.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_halo_state.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_halo_state.f90->sourcefile~rdb_ocean_periodic.f90 sourcefile~rdb_ocean_halo_state.f90->sourcefile~rdb_ocean_surface_stress.f90 sourcefile~rdb_ocean_halo_state.f90->sourcefile~rdb_profiler.f90 sourcefile~rdb_ocean_halo_state.f90->sourcefile~rdb_ocean_fold_apply.f90 sourcefile~rdb_ocean_halo_state.f90->sourcefile~rdb_ocean_halo.f90 sourcefile~rdb_ocean_halo_state.f90->sourcefile~rdb_ocean_halo_counters.f90 sourcefile~rdb_ocean_ideal_age.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_ideal_age.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_ideal_age.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_ke_probe.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_ke_probe.f90->sourcefile~rdb_coriolis_adv.f90 sourcefile~rdb_ocean_ke_probe.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_ke_probe.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_ke_probe.f90->sourcefile~rdb_ocean_metrics.f90 sourcefile~rdb_ocean_min_thickness.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_min_thickness.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_min_thickness.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_min_thickness.f90->sourcefile~rdb_remap_column.f90 sourcefile~rdb_ocean_obc_baroclinic.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_obc_baroclinic.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_obc_baroclinic.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_obc_baroclinic.f90->sourcefile~rdb_ocean_boundary_types.f90 sourcefile~rdb_ocean_obc_baroclinic.f90->sourcefile~rdb_barotropic_workstate.f90 sourcefile~rdb_ocean_pgf_reconstruct.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_pgf_reconstruct.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_porous.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_remap.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_ocean_remap.f90->sourcefile~rdb_eos.f90 sourcefile~rdb_ocean_remap.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_ocean_remap.f90->sourcefile~rdb_multilayer_state.f90 sourcefile~rdb_ocean_remap.f90->sourcefile~rdb_ocean_vcoord.f90 sourcefile~rdb_ocean_remap.f90->sourcefile~rdb_remap_column.f90 sourcefile~rdb_ocean_remap.f90->sourcefile~rdb_tracer.f90 sourcefile~rdb_ocean_tide_astro.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_recon_weno.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_recon_weno.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_scratch_3d.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_scratch_3d.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_tracer.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_tracer.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_tracer.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_vcoord.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_bt_cont_type.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_bt_cont_type.f90->sourcefile~rdb_barotropic_workstate.f90 sourcefile~rdb_console_stats.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_console_stats.f90->sourcefile~rdb_efp.f90

Files dependent on this one

sourcefile~~rdb_ocean_diag_derived.f90~~AfferentGraph sourcefile~rdb_ocean_diag_derived.f90 rdb_ocean_diag_derived.F90 sourcefile~rdb_ocean_api.f90 rdb_ocean_api.F90 sourcefile~rdb_ocean_api.f90->sourcefile~rdb_ocean_diag_derived.f90 sourcefile~rdb_ocean_engine.f90 rdb_ocean_engine.F90 sourcefile~rdb_ocean_api.f90->sourcefile~rdb_ocean_engine.f90 sourcefile~rdb_handle.f90 rdb_handle.F90 sourcefile~rdb_ocean_api.f90->sourcefile~rdb_handle.f90 sourcefile~rdb_ocean_engine.f90->sourcefile~rdb_ocean_diag_derived.f90 sourcefile~rdb_driver.f90 rdb_driver.F90 sourcefile~rdb_driver.f90->sourcefile~rdb_ocean_engine.f90 sourcefile~rdb_handle.f90->sourcefile~rdb_ocean_engine.f90

Source Code

!! Library of derived ocean diagnostics — static catalog binding a
!! diagnostic name to a fill procedure + CF-1.8 metadata, picked by
!! name from the namelist.  Every fill is a pure function of the
!! current `ocean_state_t`; outputs at cell centres (vgrid LAYER,
!! z-level remap via `remap_layer_to_z`).  Includes the opt-in sea-ice
!! drift diagnostics (`ice_speed`/`ice_u`/`ice_v`) — the canonical
!! `ice_conc`/`ice_thick` fills live in `rdb_ocean_diag_fills` (module-
!! cycle rule: this module USES that one).
module rdb_ocean_diag_derived
   use, intrinsic :: ieee_arithmetic, only: ieee_value, ieee_quiet_nan
#ifdef LFORTRAN_PASSING
   use rdb_constants, only: wp, GRAVITY, H_VANISHED
#else
   use rdb_constants, only: wp, GRAVITY, H_VANISHED, NZ_STACK_MAX
#endif
   use rdb_ocean_state, only: ocean_state_t
   use rdb_ocean_diag, only: ocean_diag_t, diag_fill_proc, diag_remap_proc, &
                             DIAG_OP_MEAN, DIAG_OP_INSTANT, DIAG_OP_UNSET, &
                             DIAG_VGRID_LAYER, DIAG_VGRID_SURFACE, DIAG_COORD_UNSET, &
                             DIAG_VGRID_DENSITY, diag_spec_t, parse_diag_spec, &
                             DIAG_MISSING_VALUE
   use rdb_ocean_diag_fills, only: register_default_diags, is_canonical_diag_name, &
                                   coord_remap_proc, diag_mask_vanished_is_on, &
                                   canonical_diag_gate_hint
   use pic_logger, only: global_logger
   use rdb_error_ring, only: error_ring_push
   implicit none
   private

#ifdef LFORTRAN_PASSING
   integer, parameter :: NZ_STACK_MAX = 64
      !! LFortran 0.64 workaround: module-local copy of the rdb_constants value
      !! (an imported parameter used as an explicit-shape dummy bound inside a
      !! PURE call becomes an impure getter under LFortran). Keep in sync (=64).
#endif

   public :: derived_entry_t
   public :: register_derived, apply_diag_selection
   public :: derived_catalog_size, derived_catalog_name, derived_catalog_requires
   public :: fill_h_layer, fill_rho_layer, fill_vorticity_z, fill_vorticity_z_impl
   public :: fill_ke_total, fill_transport_x, fill_transport_y
   public :: fill_mld_density
   public :: fill_ice_speed, fill_ice_u, fill_ice_v
   public :: fill_melt, fill_melt_m_per_yr, fill_thermal_driving
   public :: fill_haline_driving, fill_tbdry, fill_sbdry, fill_tfreeze_ib
   public :: fill_exch_vel_t, fill_exch_vel_s, fill_ustar_shelf
   public :: fill_cavity_melt_status, fill_z_draft, fill_water_column
   public :: cavity_mask_impl, melt_m_per_yr_factor

   integer, parameter, public :: DERIVED_REQ_NONE = 0
      !! No prerequisite — the entry reads state that always exists.
   integer, parameter, public :: DERIVED_REQ_CAVITY_DYN = 1
      !! Needs `&ocean_cavity_dyn_nml enable` (the draft geometry).
   integer, parameter, public :: DERIVED_REQ_CAVITY_MELT = 2
      !! Needs `&ocean_cavity_melt_nml enable` (the melt slot), which in
      !! turn requires `&ocean_cavity_dyn_nml`.

   type :: derived_entry_t
      !! One entry in the static catalog.  Buffer layout is implicit
      !! in `is_layered`: layered → (nx, ny, nz_ml), 2D → (nx, ny, 1).
      character(len=64)  :: name = ""
      character(len=128) :: long_name = ""
      character(len=32)  :: units = ""
      character(len=64)  :: standard_name = ""
      procedure(diag_fill_proc), pointer, nopass :: fill => null()
      logical :: is_layered = .true.
      integer :: requires = DERIVED_REQ_NONE
         !! Prerequisite knob, if any.  Registering an entry whose
         !! prerequisite is off FAILS LOUD at configure — the same
         !! stance `register_derived` already takes on an unknown name,
         !! and for the same reason: a requested diagnostic that comes
         !! back as a plane of missing values, or worse as a plane of
         !! zeros, is indistinguishable from a physical answer.
      logical :: masks_land = .false.
         !! The fill writes `DIAG_MISSING_VALUE` at land T-cells, so the
         !! NetCDF variable advertises `_FillValue` on BOTH registration
         !! paths, independent of `requires` and `mask_vanished_layers`.
   end type derived_entry_t

   integer, parameter :: N_CATALOG = 23
   type(derived_entry_t) :: CATALOG(N_CATALOG)
   logical :: catalog_initialised = .false.

   real(wp), parameter :: MLD_DENSITY_THRESHOLD = 0.03_wp
      !! De Boyer Montégut (2004) MLD criterion: Δσ_0 = 0.03 kg/m³ vs surface.

   real(wp), parameter :: RHO_FRESHWATER_ISOMIP = 1000.0_wp
      !! Freshwater density (kg/m³) the ISOMIP+ melt-rate CONVENTION
      !! divides by — Asay-Davis et al. (2016), *GMD* **9**, 2471–2497,
      !! §3.3: melt rates are reported in m/yr of ICE-EQUIVALENT
      !! freshwater.  It is a reporting convention, deliberately NOT the
      !! model's Boussinesq `rho_0` (1035) and NOT the melt law's own
      !! `const%rho_w`: quoting `melt_m_per_yr` against anything else
      !! puts the number 3.5 % off every published ISOMIP+ figure.
   real(wp), parameter :: SECONDS_PER_YEAR = 365.0_wp*86400.0_wp
      !! 365-day year, the ISOMIP+ protocol's own calendar.  A Julian
      !! year (365.25 d) would move every melt rate by 0.07 %, which is
      !! below the noise but not below the reader's attention.

contains

   subroutine ensure_catalog_initialised()
      !! Populate the catalog at runtime (procedure pointers can't be a
      !! parameter constructor).  Idempotent.
      if (catalog_initialised) return
      CATALOG(1) = derived_entry_t( &
                   name="h_layer", &
                   long_name="layer_thickness", &
                   units="m", &
                   standard_name="ocean_layer_thickness", &
                   fill=fill_h_layer, is_layered=.true.)
      CATALOG(2) = derived_entry_t( &
                   name="rho_layer", &
                   long_name="layer_in_situ_density", &
                   units="kg m-3", &
                   standard_name="sea_water_density", &
                   fill=fill_rho_layer, is_layered=.true.)
      CATALOG(3) = derived_entry_t( &
                   name="vorticity_z", &
                   long_name="vertical_relative_vorticity_at_cell_centre", &
                   units="s-1", &
                   standard_name="ocean_relative_vorticity", &
                   fill=fill_vorticity_z, is_layered=.true., masks_land=.true.)
      CATALOG(4) = derived_entry_t( &
                   name="ke_total", &
                   long_name="depth_integrated_kinetic_energy", &
                   units="m3 s-2", &
                   standard_name="ocean_kinetic_energy_content", &
                   fill=fill_ke_total, is_layered=.false.)
      CATALOG(5) = derived_entry_t( &
                   name="transport_x", &
                   long_name="depth_integrated_eastward_transport", &
                   units="m2 s-1", &
                   standard_name="ocean_volume_transport_x", &
                   fill=fill_transport_x, is_layered=.false.)
      CATALOG(6) = derived_entry_t( &
                   name="transport_y", &
                   long_name="depth_integrated_northward_transport", &
                   units="m2 s-1", &
                   standard_name="ocean_volume_transport_y", &
                   fill=fill_transport_y, is_layered=.false.)
      CATALOG(7) = derived_entry_t( &
                   name="mld_density", &
                   long_name="mixed_layer_depth_density_threshold", &
                   units="m", &
                   standard_name="ocean_mixed_layer_thickness_defined_by_sigma_t", &
                   fill=fill_mld_density, is_layered=.false.)
      CATALOG(8) = derived_entry_t( &
                   name="ice_speed", &
                   long_name="sea_ice_drift_speed_at_cell_centre", &
                   units="m s-1", &
                   standard_name="sea_ice_speed", &
                   fill=fill_ice_speed, is_layered=.false.)
      CATALOG(9) = derived_entry_t( &
                   name="ice_u", &
                   long_name="eastward_sea_ice_velocity_at_cell_centre", &
                   units="m s-1", &
                   standard_name="sea_ice_x_velocity", &
                   fill=fill_ice_u, is_layered=.false.)
      CATALOG(10) = derived_entry_t( &
                    name="ice_v", &
                    long_name="northward_sea_ice_velocity_at_cell_centre", &
                    units="m s-1", &
                    standard_name="sea_ice_y_velocity", &
                    fill=fill_ice_v, is_layered=.false.)
      ! ---- Ice-shelf cavity (P2c).  Eleven melt-interface fields, all
      ! gated on `&ocean_cavity_melt_nml enable`, plus two GEOMETRY
      ! fields that need only `&ocean_cavity_dyn_nml`.  Every one is
      ! NaN outside the cover, so a domain mean over the output is a
      ! mean over the CAVITY — see `cavity_mask_impl`.
      CATALOG(11) = derived_entry_t( &
                    name="melt", &
                    long_name="ice_shelf_basal_melt_mass_flux", &
                    units="kg m-2 s-1", &
                    standard_name="water_flux_into_sea_water_from_ice_shelf", &
                    fill=fill_melt, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_MELT)
      CATALOG(12) = derived_entry_t( &
                    name="melt_m_per_yr", &
                    long_name="ice_shelf_basal_melt_rate_isomip_convention", &
                    units="m yr-1", &
                    standard_name="ice_shelf_basal_melt_rate", &
                    fill=fill_melt_m_per_yr, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_MELT)
      CATALOG(13) = derived_entry_t( &
                    name="thermal_driving", &
                    long_name="far_field_thermal_driving_above_in_situ_freezing_point", &
                    units="degC", &
                    standard_name="ocean_thermal_driving", &
                    fill=fill_thermal_driving, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_MELT)
      CATALOG(14) = derived_entry_t( &
                    name="haline_driving", &
                    long_name="far_field_haline_driving_above_interface_salinity", &
                    units="g kg-1", &
                    standard_name="ocean_haline_driving", &
                    fill=fill_haline_driving, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_MELT)
      CATALOG(15) = derived_entry_t( &
                    name="tbdry", &
                    long_name="ice_ocean_interface_temperature", &
                    units="degC", &
                    standard_name="sea_water_temperature_at_ice_shelf_base", &
                    fill=fill_tbdry, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_MELT)
      CATALOG(16) = derived_entry_t( &
                    name="sbdry", &
                    long_name="ice_ocean_interface_salinity", &
                    units="g kg-1", &
                    standard_name="sea_water_salinity_at_ice_shelf_base", &
                    fill=fill_sbdry, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_MELT)
      CATALOG(17) = derived_entry_t( &
                    name="tfreeze_ib", &
                    long_name="in_situ_freezing_point_of_the_far_field_at_the_ice_base", &
                    units="degC", &
                    standard_name="sea_water_freezing_temperature", &
                    fill=fill_tfreeze_ib, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_MELT)
      CATALOG(18) = derived_entry_t( &
                    name="exch_vel_t", &
                    long_name="thermal_exchange_velocity_at_the_ice_base", &
                    units="m s-1", &
                    standard_name="ocean_thermal_exchange_velocity", &
                    fill=fill_exch_vel_t, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_MELT)
      CATALOG(19) = derived_entry_t( &
                    name="exch_vel_s", &
                    long_name="haline_exchange_velocity_at_the_ice_base", &
                    units="m s-1", &
                    standard_name="ocean_haline_exchange_velocity", &
                    fill=fill_exch_vel_s, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_MELT)
      CATALOG(20) = derived_entry_t( &
                    name="ustar_shelf", &
                    long_name="friction_velocity_of_the_ice_shelf_melt_law", &
                    units="m s-1", &
                    standard_name="ocean_friction_velocity_at_ice_shelf_base", &
                    fill=fill_ustar_shelf, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_MELT)
      CATALOG(21) = derived_entry_t( &
                    name="cavity_melt_status", &
                    long_name="per_column_basal_melt_solver_status_code", &
                    units="1", &
                    standard_name="ocean_basal_melt_solver_status", &
                    fill=fill_cavity_melt_status, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_MELT)
      CATALOG(22) = derived_entry_t( &
                    name="z_draft", &
                    long_name="ice_shelf_draft_below_the_geoid", &
                    units="m", &
                    standard_name="ice_shelf_draft", &
                    fill=fill_z_draft, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_DYN)
      CATALOG(23) = derived_entry_t( &
                    name="water_column", &
                    long_name="water_column_thickness_under_the_ice_shelf", &
                    units="m", &
                    standard_name="sea_water_column_thickness", &
                    fill=fill_water_column, is_layered=.false., &
                    requires=DERIVED_REQ_CAVITY_DYN)
      catalog_initialised = .true.
   end subroutine ensure_catalog_initialised

   function derived_catalog_size() result(n)
      !! Public only for the unit-test suite.
      integer :: n
      call ensure_catalog_initialised()
      n = N_CATALOG
   end function derived_catalog_size

   function derived_catalog_name(i) result(name)
      !! Public only for the unit-test suite.
      integer, intent(in) :: i
      character(len=64) :: name
      call ensure_catalog_initialised()
      name = CATALOG(i)%name
   end function derived_catalog_name

   function derived_catalog_requires(name) result(req)
      !! The `DERIVED_REQ_*` code a catalog entry is gated on, `-1` for
      !! an unknown name.  The DECISION `register_derived` fails loud on,
      !! exposed as a lookup so the suite can assert it without
      !! provoking `error stop` — the repo's standing pattern for
      !! testing a fail-loud rule.
      character(len=*), intent(in) :: name
      integer :: req
      integer :: i
      call ensure_catalog_initialised()
      req = -1
      do i = 1, N_CATALOG
         if (trim(CATALOG(i)%name) == trim(name)) then
            req = CATALOG(i)%requires
            return
         end if
      end do
   end function derived_catalog_requires

   subroutine register_derived(state, name, time_op, dt_out, coord)
      !! Register ONE derived diagnostic by catalog `name` (used by
      !! `apply_diag_selection`): look it up and forward to
      !! `state%diag%register(...)` with the catalog metadata + correct buffer
      !! shape.  Error-stops on an unknown name.  `coord` (a `DIAG_VGRID_*`)
      !! sets the output vgrid for a LAYERED diag + attaches the conservative
      !! remap (2D entries ignore it); default LAYER.  Remaps INTENSIVE.
      type(ocean_state_t), intent(inout), target :: state
      character(len=*), intent(in) :: name
      integer, intent(in), optional :: time_op
      real(wp), intent(in), optional :: dt_out
      integer, intent(in), optional :: coord
      integer :: i, idx, nx, ny, nz, n3, ocoord
      type(derived_entry_t) :: entry
      procedure(diag_remap_proc), pointer :: remap

      call ensure_catalog_initialised()

      idx = 0
      do i = 1, N_CATALOG
         if (trim(CATALOG(i)%name) == trim(name)) then
            idx = i
            exit
         end if
      end do
      if (idx == 0) then
         call error_ring_push("unknown derived diagnostic '"//trim(name)// &
                              "'; valid names: "//catalog_name_list())
         call global_logger%error("unknown derived diagnostic '"//trim(name)// &
                                  "'; valid names: "//catalog_name_list())
         error stop "register_derived: unknown derived diagnostic name"
      end if
      entry = CATALOG(idx)

      ! Prerequisite gate.  FAIL LOUD, never a silent plane of zeros or
      ! of missing values: a user who asked for `melt` on a run with no
      ! melt slot has made a configuration error, and handing them a
      ! NetCDF variable full of `_FillValue` would let it reach a figure.
      select case (entry%requires)
      case (DERIVED_REQ_CAVITY_DYN)
         if (.not. state%metrics%use_cavity) then
            call derived_requires_fail(trim(entry%name), "&ocean_cavity_dyn_nml enable", &
                                       "the ice-shelf draft geometry")
         end if
      case (DERIVED_REQ_CAVITY_MELT)
         if (.not. state%cavity_flux%enable) then
            call derived_requires_fail(trim(entry%name), "&ocean_cavity_melt_nml enable", &
                                       "the basal-melt interface slot")
         end if
      case default
         continue
      end select

      nx = size(state%barotropic%h, 1)
      ny = size(state%barotropic%h, 2)
      nz = state%multilayer%nz_ml
      n3 = nz
      if (.not. entry%is_layered) n3 = 1

      ocoord = DIAG_VGRID_LAYER
      if (present(coord) .and. entry%is_layered) ocoord = coord
      call coord_remap_proc(ocoord, remap)

      if (associated(remap)) then
         call state%diag%register(name=trim(entry%name), units=trim(entry%units), &
                                  fill=entry%fill, n1=nx, n2=ny, n3=n3, &
                                  long_name=trim(entry%long_name), &
                                  standard_name=trim(entry%standard_name), &
                                  time_op=time_op, dt_out=dt_out, &
                                  output_vgrid=ocoord, remap=remap, is_extensive=.false., &
                                  ! A `masks_land` entry (`vorticity_z`) writes
                                  ! `DIAG_MISSING_VALUE` at every land T-cell on this
                                  ! (remapped, layered) path too, so it must advertise
                                  ! `_FillValue` here as well as below.
                                  has_missing=((diag_mask_vanished_is_on() .and. &
                                                ocoord /= DIAG_VGRID_DENSITY) .or. &
                                               entry%masks_land))
      else
         ! Every cavity entry writes the NaN sentinel outside the cover
         ! (`cavity_mask_impl`), so the NetCDF variable must advertise a
         ! `_FillValue` — unconditionally, not via
         ! `diag_mask_vanished_is_on()`, which gates the REMAP path's
         ! below-target fill and has nothing to do with a calving front.
         ! A `masks_land` entry (`vorticity_z`, `fill_vorticity_z_impl`)
         ! writes `DIAG_MISSING_VALUE` at every land T-cell regardless of
         ! `mask_vanished_layers`, so it advertises unconditionally too.
         call state%diag%register(name=trim(entry%name), units=trim(entry%units), &
                                  fill=entry%fill, n1=nx, n2=ny, n3=n3, &
                                  long_name=trim(entry%long_name), &
                                  standard_name=trim(entry%standard_name), &
                                  time_op=time_op, dt_out=dt_out, &
                                  has_missing=(entry%requires /= DERIVED_REQ_NONE .or. &
                                               entry%masks_land))
      end if
   end subroutine register_derived

   subroutine derived_requires_fail(name, knob, what)
      !! Fail loud on a derived diagnostic whose prerequisite knob is
      !! off.  Same three-step shape `register_derived` uses for an
      !! unknown name — error ring, logger, `error stop` — so the C ABI
      !! and the console both see it.
      character(len=*), intent(in) :: name
         !! Catalog name the user asked for.
      character(len=*), intent(in) :: knob
         !! The namelist key that has to be on.
      character(len=*), intent(in) :: what
         !! One phrase naming what that knob builds.
      character(len=:), allocatable :: msg
      msg = "&ocean_diag_nml diags requested '"//name//"', which reads "//what// &
            " and therefore requires "//knob//"=.true.  Refused rather than "// &
            "registered: the fill would be a plane of missing values, which is "// &
            "indistinguishable from a physical answer once it reaches a figure."
      call error_ring_push(msg)
      call global_logger%error(msg)
      error stop "register_derived: derived diagnostic requires a knob that is off"
   end subroutine derived_requires_fail

   subroutine apply_diag_selection(state, spec, dt_out, default_coord)
      !! Configure the ocean diagnostic set from the unified
      !! `&ocean_diag_nml diags` selection string.  Single production entry
      !! point: parses `spec` once, registers the canonical defaults
      !! (consulting the spec for per-diagnostic `:off` skips and
      !! `:cadence` / `:op` / `:coord` overrides), then registers any spec
      !! entries that name a derived-catalog diagnostic (with their overrides).
      !!
      !! `default_coord` (a `DIAG_VGRID_*`, default LAYER) is the global
      !! output vgrid (`&ocean_diag_nml vgrid`) applied to layered diagnostics
      !! that don't carry a per-diag `:coord`.
      !!
      !! An empty / blank `spec` + LAYER default reproduces the canonical set
      !! exactly (bit-identical).  A spec name that is neither canonical nor
      !! in the derived catalog fails loud via `register_derived`.  A `:off`
      !! on a non-canonical name that is not registered is a harmless no-op.
      !!
      !! Must be called AFTER the output-level setters (`set_output_z_levels`
      !! / `set_output_sigma_levels` / `set_output_zstar_levels` /
      !! `set_output_density_levels`) so non-layer diagnostics size their
      !! remap targets correctly.
      type(ocean_state_t), intent(inout), target :: state
      character(len=*), intent(in) :: spec
      real(wp), intent(in), optional :: dt_out
      integer, intent(in), optional :: default_coord
      type(diag_spec_t), allocatable :: specs(:)
      integer :: i, op, dcoord, coord
      real(wp) :: dtout, dto

      dtout = 3600.0_wp
      if (present(dt_out)) dtout = dt_out
      dcoord = DIAG_VGRID_LAYER
      if (present(default_coord)) dcoord = default_coord

      specs = parse_diag_spec(spec)

      ! Canonical set, with the spec's per-diagnostic skips / overrides.
      call register_default_diags(state, dt_out=dtout, specs=specs, default_coord=dcoord)

      ! Derived-catalog additions: any spec entry that is not a canonical
      ! diagnostic and is not turned off.
      do i = 1, size(specs)
         if (specs(i)%off) cycle
         if (is_canonical_diag_name(trim(specs(i)%name))) then
            if (.not. state%diag%is_registered(trim(specs(i)%name))) then
               call global_logger%warning( &
                  "&ocean_diag_nml diags requested '"//trim(specs(i)%name)// &
                  "', which is a canonical diagnostic but is NOT registered — it will "// &
                  "be absent from the output. "//gate_clause(trim(specs(i)%name)))
            end if
            cycle
         end if
         op = DIAG_OP_INSTANT
         if (specs(i)%time_op /= DIAG_OP_UNSET) op = specs(i)%time_op
         dto = dtout
         if (specs(i)%dt_out > 0.0_wp) dto = specs(i)%dt_out
         coord = dcoord
         if (specs(i)%coord /= DIAG_COORD_UNSET) coord = specs(i)%coord
         call register_derived(state, trim(specs(i)%name), time_op=op, dt_out=dto, coord=coord)
      end do
   end subroutine apply_diag_selection

   pure function gate_clause(name) result(clause)
      !! Render `canonical_diag_gate_hint(name)` into a human-readable
      !! sentence for the "requested but not registered" warning.  Phrased
      !! as a QUESTION, never a diagnosis: the hint is a hand-maintained
      !! mirror of `register_default_diags`'s gates (§11.2 of the PR-64
      !! plan) and can drift from the true cause.  An empty hint means the
      !! diagnostic is one of the four unconditional ones (SSH/u/v/KE) and
      !! SHOULD have registered — that is a bug, not a closed gate.
      character(len=*), intent(in) :: name
      character(len=96) :: clause
      character(len=64) :: hint

      hint = canonical_diag_gate_hint(name)
      if (len_trim(hint) > 0) then
         clause = "Is "//trim(hint)//" off?"
      else
         clause = "This diagnostic has no feature gate — please report this."
      end if
   end function gate_clause

   function catalog_name_list() result(list)
      !! Comma-separated list of catalog diagnostic names (for error text).
      character(len=:), allocatable :: list
      integer :: i
      call ensure_catalog_initialised()
      list = ""
      do i = 1, N_CATALOG
         if (i > 1) list = list//", "
         list = list//trim(CATALOG(i)%name)
      end do
   end function catalog_name_list

   ! ---------------------------------------------------------------------
   ! Fill procedures
   ! ---------------------------------------------------------------------

   ! Outer-shim + flat-impl: public fills are host-side `select type`
   ! shims that deref the multilayer slot then forward device-resident
   ! arrays to a `do concurrent` `_impl` — keeps polymorphic dispatch out
   ! of the device kernel.

   subroutine fill_h_layer(state_handle, buf)
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call copy3_impl(state%multilayer%h_layer, buf)
      end select
   end subroutine fill_h_layer

   subroutine fill_rho_layer(state_handle, buf)
      !! In-situ density per layer — direct read of the EOS slot (driver
      !! must have run `ocean_eos_compute` this step; not re-invoked here),
      !! with the NaN missing-data sentinel on every vanished layer.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call fill_rho_layer_impl(state%multilayer%h_layer, &
                                  state%multilayer%rho_layer, buf)
      end select
   end subroutine fill_rho_layer

   pure subroutine fill_rho_layer_impl(h_layer, rho_layer, buf)
      !! `buf = rho_layer` on live layers, IEEE NaN on vanished ones.
      !!
      !! The EOS deliberately evaluates a vanished layer at the reference
      !! `T_ref`/`S_ref`, so `rho_layer` holds `rho_0` there (README
      !! consumer table: a filler must not perturb the PGF's density
      !! column).  That is a plausible-looking density, not a measurement,
      !! so the diagnostic reports it as missing — the same convention
      !! `fill_tracer_impl` applies to the T and S it is computed from.
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      real(wp), intent(in)    :: h_layer(:, :, :)
      real(wp), intent(in)    :: rho_layer(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, k, nx, ny, nz
      real(wp) :: qnan
      nx = min(size(buf, 1), size(rho_layer, 1), size(h_layer, 1))
      ny = min(size(buf, 2), size(rho_layer, 2), size(h_layer, 2))
      nz = min(size(buf, 3), size(rho_layer, 3), size(h_layer, 3))
      ! Sentinel computed once on the HOST (the `fill_tracer_impl` pattern).
      qnan = ieee_value(0.0_wp, ieee_quiet_nan)
      do concurrent(k=1:nz, j=1:ny, i=1:nx)
         ! vanished-ok: diagnostics report a vanished layer as NaN, not
         ! the EOS's reference-density substitution.
         if (rdb_vl_is_live(h_layer(i, j, k))) then
            buf(i, j, k) = rho_layer(i, j, k)
         else
            buf(i, j, k) = qnan
         end if
      end do
   end subroutine fill_rho_layer_impl

   pure subroutine copy3_impl(src, buf)
      !! Shared device copy `buf = src` with shape clipping — every
      !! direct-copy derived field routes through here.
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      real(wp), intent(in)    :: src(:, :, :)
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, k, nx, ny, nz
      nx = min(size(buf, 1), size(src, 1))
      ny = min(size(buf, 2), size(src, 2))
      nz = min(size(buf, 3), size(src, 3))
      do concurrent(k=1:nz, j=1:ny, i=1:nx)
         buf(i, j, k) = src(i, j, k)
      end do
   end subroutine copy3_impl

   subroutine fill_vorticity_z(state_handle, buf)
      !! The model's OWN relative vorticity ζ = ∂v/∂x − ∂u/∂y, at the same
      !! C-grid corners `coriolis_adv` computes it at (circulation/area
      !! form, C1 slip factor), averaged corner -> cell centre.  See
      !! `fill_vorticity_z_impl` for the formula and why it replaced a
      !! centred T-point stencil that differenced ocean velocity straight
      !! against the zero stored at land faces (a spurious no-slip-like
      !! vorticity sheet at every coast, even under the free-slip default).
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         if (.not. state%metrics%is_init) then
            call zero3_impl(buf)
            return
         end if
         call fill_vorticity_z_impl(state%multilayer%u_face_x_layer, &
                                    state%multilayer%v_face_y_layer, &
                                    state%metrics%dyCv, &
                                    state%metrics%dxCu, &
                                    state%metrics%wet_q, &
                                    state%metrics%wet_T, &
                                    state%metrics%iareaBu, &
                                    state%coriolis_adv%no_slip, &
                                    state%multilayer%nz_ml, buf)
      end select
   end subroutine fill_vorticity_z

   pure subroutine fill_vorticity_z_impl(u_face, v_face, dyCv, dxCu, wet_q, wet_T, &
                                         iareaBu, no_slip, nz_ml, buf)
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded);
      ! face-sized u_face/v_face and the Cv/Cu/Bu metrics carry the natural
      ! (nx[+1], ny[+1]) C-grid stagger; size() min-clips at call.
      !! Cell-centred relative vorticity that MIRRORS the dynamics' own
      !! corner ζ bit-for-bit — the shared `rdb_rvc_zeta_corner` body
      !! (`src/shared_module_utilities/rdb_rel_vort_corner.inc`), the same
      !! circulation-form formula `coriolis_adv_compute_tendencies` Pass 1
      !! evaluates inline for its `q_corner` scratch
      !! (`src/core/ocean/kernels/coriolis_adv/rdb_coriolis_adv.F90`), incl.
      !! the C1 slip factor: `no_slip=.false.` (default, free-slip) masks a
      !! land corner (`wet_q=0`) to zero rel-vort; `.true.` (no-slip) gives
      !! it the `2-wet_q` image-vorticity value instead.
      !!
      !! The 4 corners of each T-cell (SW=(i,j), SE=(i+1,j), NW=(i,j+1),
      !! NE=(i+1,j+1) in the corner-storage convention `q_corner(i,j)` sits
      !! at (i-1/2,j-1/2)) are averaged onto the cell centre with a plain
      !! `0.25*(sw+se+nw+ne)` — the SAME fixed-count average the dynamics
      !! itself uses to interpolate `q_corner` onto a u/v-face
      !! (`zeta_at_u = 0.5*(q_corner(i,j)+q_corner(i,j+1))`), just over 4
      !! corners instead of 2.  It is deliberately NOT re-weighted by
      !! `wet_q`: each corner's OWN value already carries the correct
      !! land/coast physics via the C1 factor above (free-slip -> exactly
      !! 0 at a land corner, so it dilutes a coastal cell's average toward
      !! 0 the same way the dynamics' own face-average does; no-slip -> the
      !! nonzero image-vorticity value, so the boundary condition actually
      !! reaches the diagnostic instead of being masked out a second time
      !! by a wet-only divisor). A land cell (`wet_T=0`) reports
      !! `DIAG_MISSING_VALUE`.
      real(wp), intent(in)    :: u_face(:, :, :), v_face(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      ! assumed-shape-ok: diag fill — cadence-bounded (once per output frame)
      real(wp), intent(in)    :: dyCv(:, :), dxCu(:, :), wet_q(:, :), wet_T(:, :)  ! assumed-shape-ok: diag fill
      real(wp), intent(in)    :: iareaBu(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      logical, intent(in)     :: no_slip
      integer, intent(in)    :: nz_ml
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, k, nx, ny, nz
      real(wp) :: ns, z_sw, z_se, z_nw, z_ne
      call zero3_impl(buf)
      nx = min(size(buf, 1), size(wet_T, 1))
      ny = min(size(buf, 2), size(wet_T, 2))
      nz = min(size(buf, 3), nz_ml)
      ns = merge(1.0_wp, 0.0_wp, no_slip)
      ! Interior cells only (i in [2, nx-1], j in [2, ny-1]), matching the
      ! predecessor stencil's rim convention: the ±1 corner reach needs
      ! i-1/i+1 and j-1/j+1 in bounds, so the outer rim stays at the zero
      ! seed exactly as before this fix (an orthogonal, pre-existing
      ! limitation of the diag's domain coverage, not part of the bug).
      do concurrent(k=1:nz, j=2:ny - 1, i=2:nx - 1) &
         local(z_sw, z_se, z_nw, z_ne)
         if (wet_T(i, j) > 0.5_wp) then
            z_sw = rdb_rvc_zeta_corner(v_face(i, j, k), v_face(i - 1, j, k), &
                                       dyCv(i, j), dyCv(i - 1, j), &
                                       u_face(i, j, k), u_face(i, j - 1, k), &
                                       dxCu(i, j), dxCu(i, j - 1), &
                                       iareaBu(i, j), wet_q(i, j), ns)
            z_se = rdb_rvc_zeta_corner(v_face(i + 1, j, k), v_face(i, j, k), &
                                       dyCv(i + 1, j), dyCv(i, j), &
                                       u_face(i + 1, j, k), u_face(i + 1, j - 1, k), &
                                       dxCu(i + 1, j), dxCu(i + 1, j - 1), &
                                       iareaBu(i + 1, j), wet_q(i + 1, j), ns)
            z_nw = rdb_rvc_zeta_corner(v_face(i, j + 1, k), v_face(i - 1, j + 1, k), &
                                       dyCv(i, j + 1), dyCv(i - 1, j + 1), &
                                       u_face(i, j + 1, k), u_face(i, j, k), &
                                       dxCu(i, j + 1), dxCu(i, j), &
                                       iareaBu(i, j + 1), wet_q(i, j + 1), ns)
            z_ne = rdb_rvc_zeta_corner(v_face(i + 1, j + 1, k), v_face(i, j + 1, k), &
                                       dyCv(i + 1, j + 1), dyCv(i, j + 1), &
                                       u_face(i + 1, j + 1, k), u_face(i + 1, j, k), &
                                       dxCu(i + 1, j + 1), dxCu(i + 1, j), &
                                       iareaBu(i + 1, j + 1), wet_q(i + 1, j + 1), ns)
            buf(i, j, k) = 0.25_wp*((z_sw + z_se) + (z_nw + z_ne))
         else
            buf(i, j, k) = DIAG_MISSING_VALUE
         end if
      end do
   end subroutine fill_vorticity_z_impl

   pure subroutine zero3_impl(buf)
      !! Device-side zero of `buf` (seeds column sums / clean bail-out).
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      real(wp), intent(inout) :: buf(:, :, :)
      integer :: i, j, k, nx, ny, nz
      nx = size(buf, 1)
      ny = size(buf, 2)
      nz = size(buf, 3)
      do concurrent(k=1:nz, j=1:ny, i=1:nx)
         buf(i, j, k) = 0.0_wp
      end do
   end subroutine zero3_impl

   subroutine fill_ke_total(state_handle, buf)
      !! Depth-integrated kinetic energy at each cell:
      !!   KE_total(i, j) = Σ_k 0.5 · h_layer(k) · (u_c² + v_c²)
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call fill_ke_total_impl(state%multilayer%h_layer, &
                                 state%multilayer%u_face_x_layer, &
                                 state%multilayer%v_face_y_layer, buf)
      end select
   end subroutine fill_ke_total

   pure subroutine fill_ke_total_impl(h_layer, u_face, v_face, buf)
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded);
      ! face-sized arrays have nx+1/ny+1 dims; size() min-clips at call.
      real(wp), intent(in)    :: h_layer(:, :, :)
      real(wp), intent(in)    :: u_face(:, :, :), v_face(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded; face-sized dims
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, k, nx, ny, nz
      real(wp) :: uc, vc, col_ke
      nx = min(size(buf, 1), size(u_face, 1) - 1, size(v_face, 1))
      ny = min(size(buf, 2), size(u_face, 2), size(v_face, 2) - 1)
      nz = min(size(u_face, 3), size(v_face, 3), size(h_layer, 3))
      ! Per-cell column sum: outer DC over (j, i), inner serial over k.
      do concurrent(j=1:ny, i=1:nx) &
         local(uc, vc, col_ke, k)
         col_ke = 0.0_wp
         do k = 1, nz
            uc = 0.5_wp*(u_face(i, j, k) + u_face(i + 1, j, k))
            vc = 0.5_wp*(v_face(i, j, k) + v_face(i, j + 1, k))
            col_ke = col_ke + 0.5_wp*h_layer(i, j, k)*(uc*uc + vc*vc)
         end do
         buf(i, j, 1) = col_ke
      end do
   end subroutine fill_ke_total_impl

   subroutine fill_transport_x(state_handle, buf)
      !! Depth-integrated zonal transport (m²/s):
      !!   T_x(i, j) = Σ_k h_c · u_c   (cell-centre form)
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call fill_transport_x_impl(state%multilayer%h_layer, &
                                    state%multilayer%u_face_x_layer, buf)
      end select
   end subroutine fill_transport_x

   pure subroutine fill_transport_x_impl(h_layer, u_face, buf)
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      real(wp), intent(in)    :: h_layer(:, :, :), u_face(:, :, :)
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, k, nx, ny, nz
      real(wp) :: u_c, col
      nx = min(size(buf, 1), size(u_face, 1) - 1)
      ny = min(size(buf, 2), size(u_face, 2))
      nz = min(size(u_face, 3), size(h_layer, 3))
      do concurrent(j=1:ny, i=1:nx) &
         local(u_c, col, k)
         col = 0.0_wp
         do k = 1, nz
            u_c = 0.5_wp*(u_face(i, j, k) + u_face(i + 1, j, k))
            col = col + h_layer(i, j, k)*u_c
         end do
         buf(i, j, 1) = col
      end do
   end subroutine fill_transport_x_impl

   subroutine fill_transport_y(state_handle, buf)
      !! Depth-integrated meridional transport (m²/s) — mirror of x.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call fill_transport_y_impl(state%multilayer%h_layer, &
                                    state%multilayer%v_face_y_layer, buf)
      end select
   end subroutine fill_transport_y

   pure subroutine fill_transport_y_impl(h_layer, v_face, buf)
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      real(wp), intent(in)    :: h_layer(:, :, :), v_face(:, :, :)
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, k, nx, ny, nz
      real(wp) :: v_c, col
      nx = min(size(buf, 1), size(v_face, 1))
      ny = min(size(buf, 2), size(v_face, 2) - 1)
      nz = min(size(v_face, 3), size(h_layer, 3))
      do concurrent(j=1:ny, i=1:nx) &
         local(v_c, col, k)
         col = 0.0_wp
         do k = 1, nz
            v_c = 0.5_wp*(v_face(i, j, k) + v_face(i, j + 1, k))
            col = col + h_layer(i, j, k)*v_c
         end do
         buf(i, j, 1) = col
      end do
   end subroutine fill_transport_y_impl

   subroutine fill_mld_density(state_handle, buf)
      !! Mixed-layer depth via the de Boyer Montégut threshold.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      integer :: nz_ml
      select type (state => state_handle)
      class is (ocean_state_t)
         nz_ml = state%multilayer%nz_ml
         if (nz_ml < 1) then
            call zero3_impl(buf)
            return
         end if
         call fill_mld_density_impl(state%multilayer%h_layer, &
                                    state%multilayer%rho_layer, &
                                    state%multilayer%k_top, &
                                    nz_ml, buf)
      end select
      if (.false.) buf(1, 1, 1) = GRAVITY  ! keep GRAVITY import live
   end subroutine fill_mld_density

   pure subroutine fill_mld_density_impl(h_layer, rho_layer, k_top, nz_ml, buf)
      !! Per-column scan from the first LIVE layer (`k_top`, which is
      !! `nz_ml` unless a rigid top has vanished the layers above it)
      !! toward the bed; first layer whose ρ exceeds (surface ρ +
      !! MLD_DENSITY_THRESHOLD) marks the MLD as the cumulative h-sum
      !! above it.  No crossing → MLD = full column depth.  Threshold met
      !! at the surface itself → MLD = 0.
      !!
      !! A vanished layer cannot mark the crossing: its `rho_layer` is the
      !! EOS's reference-density substitution (`rho_0`), not the density
      !! of any water, so a filler bed layer would otherwise read as a
      !! pycnocline whenever `rho_0` happens to exceed the surface density
      !! by the threshold.  Its (sub-`H_VANISHED`) thickness still counts
      !! toward the depth, so a column with no crossing still reports its
      !! full depth.
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      real(wp), intent(in)    :: h_layer(:, :, :), rho_layer(:, :, :)
      integer, intent(in)    :: k_top(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer, intent(in)    :: nz_ml
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, k, kt, nx, ny
      real(wp) :: rho_surf, d_acc, mld
      logical :: crossed
      nx = min(size(buf, 1), size(rho_layer, 1))
      ny = min(size(buf, 2), size(rho_layer, 2))
      do concurrent(j=1:ny, i=1:nx) &
         local(rho_surf, d_acc, mld, crossed, k, kt)
         kt = k_top(i, j)
         rho_surf = rho_layer(i, j, kt)
         d_acc = 0.0_wp
         mld = 0.0_wp
         crossed = .false.
         do k = kt, 1, -1
            if (rdb_vl_is_live(h_layer(i, j, k)) .and. &
                rho_layer(i, j, k) - rho_surf >= MLD_DENSITY_THRESHOLD) then
               mld = d_acc
               crossed = .true.
               exit
            end if
            d_acc = d_acc + h_layer(i, j, k)
         end do
         if (.not. crossed) mld = d_acc
         buf(i, j, 1) = mld
      end do
   end subroutine fill_mld_density_impl

   subroutine fill_ice_speed(state_handle, buf)
      !! Sea-ice drift speed |u_ice| at T-centres (m/s) — C-face pairs
      !! averaged to centre, 2-D twin of the ocean `fill_ke` stencil.
      !! Ice off / not init ⇒ zeros (never registered by default; opt-in
      !! via `&ocean_diag_nml diags`).
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         if (.not. state%ice%is_init) then
            call zero3_impl(buf)
            return
         end if
         call fill_ice_speed_impl(state%ice%u_ice, state%ice%v_ice, buf)
      end select
   end subroutine fill_ice_speed

   pure subroutine fill_ice_speed_impl(u_ice, v_ice, buf)
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded);
      ! face-sized u_ice/v_ice have nx+1/ny+1 dims; size() min-clips at call.
      real(wp), intent(in)    :: u_ice(:, :), v_ice(:, :)
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, nx, ny
      real(wp) :: uc, vc
      nx = min(size(buf, 1), size(u_ice, 1) - 1, size(v_ice, 1))
      ny = min(size(buf, 2), size(u_ice, 2), size(v_ice, 2) - 1)
      do concurrent(j=1:ny, i=1:nx) local(uc, vc)
         uc = 0.5_wp*(u_ice(i, j) + u_ice(i + 1, j))
         vc = 0.5_wp*(v_ice(i, j) + v_ice(i, j + 1))
         buf(i, j, 1) = sqrt(uc*uc + vc*vc)
      end do
   end subroutine fill_ice_speed_impl

   subroutine fill_ice_u(state_handle, buf)
      !! Eastward sea-ice velocity at T-centres (m/s) — u-face pair
      !! averaged to centre, 2-D twin of `fill_u_centre`.  Ice off / not
      !! init ⇒ zeros.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         if (.not. state%ice%is_init) then
            call zero3_impl(buf)
            return
         end if
         call fill_ice_u_impl(state%ice%u_ice, buf)
      end select
   end subroutine fill_ice_u

   pure subroutine fill_ice_u_impl(u_ice, buf)
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded);
      ! face-sized u_ice(:,:) has nx+1 first dim, incompatible with cell-sized buf.
      real(wp), intent(in)    :: u_ice(:, :)
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, nx, ny
      nx = min(size(buf, 1), size(u_ice, 1) - 1)
      ny = min(size(buf, 2), size(u_ice, 2))
      do concurrent(j=1:ny, i=1:nx)
         buf(i, j, 1) = 0.5_wp*(u_ice(i, j) + u_ice(i + 1, j))
      end do
   end subroutine fill_ice_u_impl

   subroutine fill_ice_v(state_handle, buf)
      !! Northward sea-ice velocity at T-centres (m/s) — v-face pair
      !! averaged to centre, 2-D twin of `fill_v_centre`.  Ice off / not
      !! init ⇒ zeros.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         if (.not. state%ice%is_init) then
            call zero3_impl(buf)
            return
         end if
         call fill_ice_v_impl(state%ice%v_ice, buf)
      end select
   end subroutine fill_ice_v

   ! ---------------------------------------------------------------------
   ! Ice-shelf cavity (P2c)
   ! ---------------------------------------------------------------------
   !
   ! Eleven melt-interface fields and two geometry fields.  Three rules
   ! run through all of them:
   !
   !   MISSING OUTSIDE THE CAVITY.  Every melt field is IEEE NaN where
   !   the column was not solved, the same sentinel `fill_tracer_impl`
   !   writes for a vanished layer, so a domain mean over the output is
   !   a mean over the CAVITY and not a cavity average diluted by a
   !   basin of zeros.  The console reduction already skips non-finite
   !   cells and reports how many it skipped, and the NetCDF writer tags
   !   the variable with `_FillValue` (`has_missing` above).  A zero
   !   would be much worse than absent here: zero melt is a LEGAL
   !   answer, and 0 m/yr averaged over open ocean is how a 30 m/yr
   !   shelf gets published as 2.
   !
   !   THE MASK IS `cavity_flux%active`, NOT `cover_frac`.  `active` is
   !   what the kernel was actually handed — covered AND wet AND "the
   !   far-field sample found mass" — so a covered column that was
   !   skipped reads missing rather than reading the zeros its outputs
   !   were left at.
   !
   !   NOTHING IS RE-DERIVED.  `exch_vel_t`/`exch_vel_s` come off the
   !   slot because under `hj99`/`yung25` they are implicit functions of
   !   the converged interface state; `tfreeze_ib` goes through the same
   !   `eos_freezing_point` handle the solve used.  A diagnostic that
   !   rebuilt either one would be a second, divergent implementation of
   !   the physics.

   pure subroutine cavity_mask_impl(src, active, buf)
      !! Copy a 2-D cavity field into the diag buffer, writing IEEE NaN
      !! wherever the column was not solved.  Every cavity fill that is
      !! a plain read of a slot array routes through here, so the
      !! missing-value convention cannot drift between them.
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      real(wp), intent(in)    :: src(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      real(wp), intent(in)    :: active(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, nx, ny
      real(wp) :: qnan
      nx = min(size(buf, 1), size(src, 1), size(active, 1))
      ny = min(size(buf, 2), size(src, 2), size(active, 2))
      ! Sentinel computed once on the HOST before the device loop —
      ! `ieee_value` is a host intrinsic (the `fill_tracer_impl` pattern).
      qnan = ieee_value(0.0_wp, ieee_quiet_nan)
      do concurrent(j=1:ny, i=1:nx)
         if (active(i, j) > 0.5_wp) then
            buf(i, j, 1) = src(i, j)
         else
            buf(i, j, 1) = qnan
         end if
      end do
   end subroutine cavity_mask_impl

   pure function melt_m_per_yr_factor() result(f)
      !! The ISOMIP+ melt-rate conversion, `kg m-2 s-1` → `m yr-1` of
      !! ice-equivalent freshwater: `f = SECONDS_PER_YEAR / rho_fw`.
      !!
      !! Asay-Davis et al. (2016), *GMD* **9**, 2471–2497 §3.3.  With
      !! `rho_fw = 1000 kg/m^3` and a 365-day year,
      !! `f = 31 536 000 / 1000 = 31 536 m yr-1 per kg m-2 s-1`, i.e. a
      !! melt flux of 1e-3 kg/m^2/s is 31.536 m/yr — hand-checkable, and
      !! the test checks it by hand.
      !!
      !! A function rather than a parameter so the test can assert the
      !! CONVERSION rather than re-typing the same two constants and
      !! asserting its own arithmetic.
      real(wp) :: f
      f = SECONDS_PER_YEAR/RHO_FRESHWATER_ISOMIP
   end function melt_m_per_yr_factor

   subroutine fill_melt(state_handle, buf)
      !! Basal melt mass flux (kg m-2 s-1), **positive = melting**.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call cavity_mask_impl(state%cavity_flux%melt, state%cavity_flux%active, buf)
      end select
   end subroutine fill_melt

   subroutine fill_melt_m_per_yr(state_handle, buf)
      !! Basal melt rate in the ISOMIP+ reporting unit (m yr-1 of
      !! ice-equivalent freshwater) — see `melt_m_per_yr_factor`.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call cavity_scale_impl(state%cavity_flux%melt, state%cavity_flux%active, &
                                melt_m_per_yr_factor(), buf)
      end select
   end subroutine fill_melt_m_per_yr

   pure subroutine cavity_scale_impl(src, active, scale, buf)
      !! `cavity_mask_impl` with a constant multiplier folded in.
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      real(wp), intent(in)    :: src(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      real(wp), intent(in)    :: active(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      real(wp), intent(in)    :: scale
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, nx, ny
      real(wp) :: qnan
      nx = min(size(buf, 1), size(src, 1), size(active, 1))
      ny = min(size(buf, 2), size(src, 2), size(active, 2))
      qnan = ieee_value(0.0_wp, ieee_quiet_nan)
      do concurrent(j=1:ny, i=1:nx)
         if (active(i, j) > 0.5_wp) then
            buf(i, j, 1) = scale*src(i, j)
         else
            buf(i, j, 1) = qnan
         end if
      end do
   end subroutine cavity_scale_impl

   subroutine fill_thermal_driving(state_handle, buf)
      !! `T* = T_far − T_f(S_far, p_top)` (degC) — the far-field
      !! temperature above the IN-SITU freezing point at the interface
      !! pressure.  Positive drives melting.  This is the single number
      !! the melt rate is roughly linear in, so it is the first thing to
      !! look at when a melt rate looks wrong.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call thermal_driving_impl(state%cavity_flux%t_far, state%cavity_flux%s_far, &
                                   state%multilayer%p_top, state%cavity_flux%active, &
                                   state%eos, buf)
      end select
   end subroutine fill_thermal_driving

   pure subroutine thermal_driving_impl(t_far, s_far, p_top, active, eos, buf)
      !! `T_far − eos_freezing_point(eos, S_far, p_top)`.  The liquidus
      !! comes off the SAME `eos_t` handle the solve used
      !! (`&ocean_eos_nml tfreeze_set`), never a local copy of the
      !! coefficients — the two sets differ by ~0.03 degC, which is
      !! enough to flip the sign of this field.
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      use rdb_eos, only: eos_t, eos_freezing_point
      real(wp), intent(in)    :: t_far(:, :), s_far(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      real(wp), intent(in)    :: p_top(:, :), active(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      type(eos_t), intent(in) :: eos
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, nx, ny
      real(wp) :: qnan
      nx = min(size(buf, 1), size(t_far, 1), size(p_top, 1), size(active, 1))
      ny = min(size(buf, 2), size(t_far, 2), size(p_top, 2), size(active, 2))
      qnan = ieee_value(0.0_wp, ieee_quiet_nan)
      do concurrent(j=1:ny, i=1:nx)
         if (active(i, j) > 0.5_wp) then
            buf(i, j, 1) = t_far(i, j) - eos_freezing_point(eos, s_far(i, j), p_top(i, j))
         else
            buf(i, j, 1) = qnan
         end if
      end do
   end subroutine thermal_driving_impl

   subroutine fill_tfreeze_ib(state_handle, buf)
      !! `T_f(S_far, p_top)` (degC) — the in-situ freezing point of the
      !! FAR FIELD at the ice base.  Distinct from `tbdry`, which is the
      !! freezing point of the INTERFACE salinity `S_b`; their
      !! difference is the whole three-equation correction, so shipping
      !! both makes it visible.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call tfreeze_ib_impl(state%cavity_flux%s_far, state%multilayer%p_top, &
                              state%cavity_flux%active, state%eos, buf)
      end select
   end subroutine fill_tfreeze_ib

   pure subroutine tfreeze_ib_impl(s_far, p_top, active, eos, buf)
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      use rdb_eos, only: eos_t, eos_freezing_point
      real(wp), intent(in)    :: s_far(:, :), p_top(:, :), active(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      type(eos_t), intent(in) :: eos
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, nx, ny
      real(wp) :: qnan
      nx = min(size(buf, 1), size(s_far, 1), size(p_top, 1), size(active, 1))
      ny = min(size(buf, 2), size(s_far, 2), size(p_top, 2), size(active, 2))
      qnan = ieee_value(0.0_wp, ieee_quiet_nan)
      do concurrent(j=1:ny, i=1:nx)
         if (active(i, j) > 0.5_wp) then
            buf(i, j, 1) = eos_freezing_point(eos, s_far(i, j), p_top(i, j))
         else
            buf(i, j, 1) = qnan
         end if
      end do
   end subroutine tfreeze_ib_impl

   subroutine fill_haline_driving(state_handle, buf)
      !! `S* = S_far − S_b` (g/kg) — the salinity contrast the haline
      !! exchange acts on.  Positive under melting (meltwater freshens
      !! the interface).
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call cavity_diff_impl(state%cavity_flux%s_far, state%cavity_flux%s_b, &
                               state%cavity_flux%active, buf)
      end select
   end subroutine fill_haline_driving

   pure subroutine cavity_diff_impl(a, b, active, buf)
      !! `a - b` with the cavity missing-value convention.
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      real(wp), intent(in)    :: a(:, :), b(:, :), active(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, nx, ny
      real(wp) :: qnan
      nx = min(size(buf, 1), size(a, 1), size(b, 1), size(active, 1))
      ny = min(size(buf, 2), size(a, 2), size(b, 2), size(active, 2))
      qnan = ieee_value(0.0_wp, ieee_quiet_nan)
      do concurrent(j=1:ny, i=1:nx)
         if (active(i, j) > 0.5_wp) then
            buf(i, j, 1) = a(i, j) - b(i, j)
         else
            buf(i, j, 1) = qnan
         end if
      end do
   end subroutine cavity_diff_impl

   subroutine fill_tbdry(state_handle, buf)
      !! Interface temperature `T_b` (degC) — on the liquidus at `S_b`.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call cavity_mask_impl(state%cavity_flux%t_b, state%cavity_flux%active, buf)
      end select
   end subroutine fill_tbdry

   subroutine fill_sbdry(state_handle, buf)
      !! Interface salinity `S_b` (g/kg).
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call cavity_mask_impl(state%cavity_flux%s_b, state%cavity_flux%active, buf)
      end select
   end subroutine fill_sbdry

   subroutine fill_exch_vel_t(state_handle, buf)
      !! Thermal exchange velocity `gamma_T` (m/s) the solve CONVERGED
      !! on — not `Gamma_T·u*` re-derived here.  Under `hj99`/`yung25`
      !! the two differ by the stratification suppression.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call cavity_mask_impl(state%cavity_flux%gamma_t, state%cavity_flux%active, buf)
      end select
   end subroutine fill_exch_vel_t

   subroutine fill_exch_vel_s(state_handle, buf)
      !! Haline exchange velocity `gamma_S` (m/s) — see `fill_exch_vel_t`.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call cavity_mask_impl(state%cavity_flux%gamma_s, state%cavity_flux%active, buf)
      end select
   end subroutine fill_exch_vel_s

   subroutine fill_ustar_shelf(state_handle, buf)
      !! Melt friction velocity `u*` (m/s), `max(sqrt(C_d(u²+v²+u_tide²)),
      !! u*_min)`.  This is the MELT law's `u*` and nothing else: it
      !! drives no momentum drag, and KPP/EPBL do not read it.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call cavity_mask_impl(state%cavity_flux%ustar, state%cavity_flux%active, buf)
      end select
   end subroutine fill_ustar_shelf

   subroutine fill_cavity_melt_status(state_handle, buf)
      !! Per-column `CAVITY_MELT_*` status code, as a real.  `0` is OK;
      !! anything else is a column that took the kernel's documented
      !! zero-melt safe state, and the console's warning line says how
      !! many there were.  Masked like the rest, so the plane cannot be
      !! read as "everything is fine" over open ocean.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call cavity_status_impl(state%cavity_flux%status, state%cavity_flux%active, buf)
      end select
   end subroutine fill_cavity_melt_status

   pure subroutine cavity_status_impl(status, active, buf)
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      integer, intent(in)     :: status(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      real(wp), intent(in)    :: active(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, nx, ny
      real(wp) :: qnan
      nx = min(size(buf, 1), size(status, 1), size(active, 1))
      ny = min(size(buf, 2), size(status, 2), size(active, 2))
      qnan = ieee_value(0.0_wp, ieee_quiet_nan)
      do concurrent(j=1:ny, i=1:nx)
         if (active(i, j) > 0.5_wp) then
            buf(i, j, 1) = real(status(i, j), wp)
         else
            buf(i, j, 1) = qnan
         end if
      end do
   end subroutine cavity_status_impl

   subroutine fill_z_draft(state_handle, buf)
      !! Ice-shelf draft (m, POSITIVE DOWN from the geoid) — geometry,
      !! so it needs only `&ocean_cavity_dyn_nml` and is masked by
      !! `cover_frac` rather than by the melt slot's `active`.  Beyond
      !! the calving front there is no draft, which is missing data, not
      !! a draft of zero.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call cavity_mask_impl(state%metrics%z_draft, state%metrics%cover_frac, buf)
      end select
   end subroutine fill_z_draft

   subroutine fill_water_column(state_handle, buf)
      !! Water-column thickness under the shelf, `D = bt_H_ref + bt_eta`
      !! (m) — the ONE expression every consumer of the column depth
      !! uses, which is exactly what the cavity datum
      !! (`bt_H_ref = b − z_draft`) buys.  Masked by `cover_frac`: the
      !! quantity is perfectly well defined in open water, but as a
      !! CAVITY diagnostic a domain mean should be the mean cavity
      !! thickness, not that diluted by the open basin.
      class(*), intent(in) :: state_handle
      real(wp), intent(inout) :: buf(:, :, :)
      select type (state => state_handle)
      class is (ocean_state_t)
         call water_column_impl(state%dyn%bt_work%bt_H_ref, state%dyn%bt_work%bt_eta, &
                                state%metrics%cover_frac, buf)
      end select
   end subroutine fill_water_column

   pure subroutine water_column_impl(bt_H_ref, bt_eta, cover, buf)
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded).
      real(wp), intent(in)    :: bt_H_ref(:, :), bt_eta(:, :), cover(:, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, nx, ny
      real(wp) :: qnan
      nx = min(size(buf, 1), size(bt_H_ref, 1), size(bt_eta, 1), size(cover, 1))
      ny = min(size(buf, 2), size(bt_H_ref, 2), size(bt_eta, 2), size(cover, 2))
      qnan = ieee_value(0.0_wp, ieee_quiet_nan)
      do concurrent(j=1:ny, i=1:nx)
         if (cover(i, j) > 0.5_wp) then
            buf(i, j, 1) = bt_H_ref(i, j) + bt_eta(i, j)
         else
            buf(i, j, 1) = qnan
         end if
      end do
   end subroutine water_column_impl

   pure subroutine fill_ice_v_impl(v_ice, buf)
      ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded);
      ! face-sized v_ice(:,:) has ny+1 second dim, incompatible with cell-sized buf.
      real(wp), intent(in)    :: v_ice(:, :)
      real(wp), intent(inout) :: buf(:, :, :)  ! assumed-shape-ok: diag fill — cadence-bounded
      integer :: i, j, nx, ny
      nx = min(size(buf, 1), size(v_ice, 1))
      ny = min(size(buf, 2), size(v_ice, 2) - 1)
      do concurrent(j=1:ny, i=1:nx)
         buf(i, j, 1) = 0.5_wp*(v_ice(i, j) + v_ice(i, j + 1))
      end do
   end subroutine fill_ice_v_impl

#include "rdb_vanished_layer.inc"
#include "rdb_rel_vort_corner.inc"

end module rdb_ocean_diag_derived