subroutine ocean_epbl_init(this, grid, nz_ml)
!! Allocate the persistent fields + column workspaces. Always
!! allocates (configure runs after init, so `enable` isn't
!! known yet); the memory cost when off is the same 7-field
!! footprint the vmix slot already pays.
class(ocean_epbl_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
allocate (this%f_centre(nx, ny), source=0.0_wp)
allocate (this%mld(nx, ny), source=0.0_wp)
allocate (this%b0(nx, ny), source=0.0_wp)
allocate (this%kd_int(nx, ny, nz + 1), source=0.0_wp)
allocate (this%la(nx, ny), source=0.0_wp)
allocate (this%tke_wind(nx, ny), source=0.0_wp)
allocate (this%tke_conv(nx, ny), source=0.0_wp)
allocate (this%tke_forcing(nx, ny), source=0.0_wp)
allocate (this%tke_mixing(nx, ny), source=0.0_wp)
allocate (this%tke_mech_decay(nx, ny), source=0.0_wp)
allocate (this%tke_conv_decay(nx, ny), source=0.0_wp)
call this%t0%init(nx, ny, nz, "epbl_t0")
call this%s0%init(nx, ny, nz, "epbl_s0")
call this%dpe_t%init(nx, ny, nz, "epbl_dpe_t")
call this%dpe_s%init(nx, ny, nz, "epbl_dpe_s")
call this%dcolht_t%init(nx, ny, nz, "epbl_dcolht_t")
call this%dcolht_s%init(nx, ny, nz, "epbl_dcolht_s")
call this%ctke_sw%init(nx, ny, nz, "epbl_ctke_sw")
this%is_init = .true.
end subroutine ocean_epbl_init