subroutine ocean_vdiff_init(this, grid, nz_ml)
class(ocean_vdiff_t), intent(inout) :: this
type(hgrid_t), intent(in) :: grid
integer, intent(in), optional :: nz_ml
integer :: nx, ny, nz
nx = grid%nx_total
ny = grid%ny_total
nz = 1
if (present(nz_ml)) nz = nz_ml
! Tracer scratch: cell-centred (nx, ny, nz)
call this%a_diag_t%init(nx, ny, nz, "ocean_vdiff_a_diag_t")
call this%b_diag_t%init(nx, ny, nz, "ocean_vdiff_b_diag_t")
call this%c_diag_t%init(nx, ny, nz, "ocean_vdiff_c_diag_t")
call this%rhs_t%init(nx, ny, nz, "ocean_vdiff_rhs_t")
! u-face scratch: (nx+1, ny, nz)
call this%a_diag_u%init(nx + 1, ny, nz, "ocean_vdiff_a_diag_u")
call this%b_diag_u%init(nx + 1, ny, nz, "ocean_vdiff_b_diag_u")
call this%c_diag_u%init(nx + 1, ny, nz, "ocean_vdiff_c_diag_u")
call this%rhs_u%init(nx + 1, ny, nz, "ocean_vdiff_rhs_u")
! v-face scratch: (nx, ny+1, nz)
call this%a_diag_v%init(nx, ny + 1, nz, "ocean_vdiff_a_diag_v")
call this%b_diag_v%init(nx, ny + 1, nz, "ocean_vdiff_b_diag_v")
call this%c_diag_v%init(nx, ny + 1, nz, "ocean_vdiff_c_diag_v")
call this%rhs_v%init(nx, ny + 1, nz, "ocean_vdiff_rhs_v")
! Cell-centred diffusivity workspace: (nx, ny, nz+1).
call this%kv_scalar_buf%init(nx, ny, nz + 1, "ocean_vdiff_kv_scalar_buf")
! Per-face bottom boundary layer (2-D, cheap): filled by
! `vdiff_set_viscous_bbl`, or with the glue constants.
allocate (this%kv_bbl_u(nx + 1, ny), source=0.0_wp)
allocate (this%kv_bbl_v(nx, ny + 1), source=0.0_wp)
allocate (this%bbl_thick_u(nx + 1, ny), source=0.0_wp)
allocate (this%bbl_thick_v(nx, ny + 1), source=0.0_wp)
! Concentration workspace: sized by `vdiff_bbl_configure` (before
! `enter_data`) only when the per-face BBL is on.
allocate (this%bbl_conc_t(1, 1, 1), source=0.0_wp)
allocate (this%bbl_conc_s(1, 1, 1), source=0.0_wp)
this%is_init = .true.
end subroutine ocean_vdiff_init