cavity_mass_totals_impl Subroutine

public pure subroutine cavity_mass_totals_impl(nx, ny, nghost, dt_over_rho0, active, wet_mask, cover_frac, melt, areaT, vol_melt, area_open)

The two INTERIOR integrals the mass budget and the compensation sink need, reduced on device in one pass:

vol_melt — the meltwater volume (m^3) added this step, sum(melt*dt/rho_0 * areaT) over active columns; area_open — the wet area (m^2) the ice does NOT cover.

GHOSTS ARE EXCLUDED (nghost+1 .. n-nghost), exactly as ocean_accumulate_mass_out excludes them: the console’s totals are interior integrals, so a source term that counted the halo would be measuring a different domain than the total it has to close. The per-cell APPLY still runs over the whole array, like every other surface kernel — the halo exchange owns the ghosts.

melt*dt_over_rho0 is formed with the same scalar and in the same order as the apply kernel’s dh, so the two agree to the last bit per cell and the residual is reduction round-off only.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx

First dimension (ghosts included).

integer, intent(in) :: ny

Second dimension.

integer, intent(in) :: nghost

Halo width to exclude on every side.

real(kind=wp), intent(in) :: dt_over_rho0

dt/rho_0.

real(kind=wp), intent(in) :: active(nx,ny)

Composed solve mask.

real(kind=wp), intent(in) :: wet_mask(nx,ny)

Static wet (1) / land (0) mask.

real(kind=wp), intent(in) :: cover_frac(nx,ny)

Ice-cover fraction (v1 binary).

real(kind=wp), intent(in) :: melt(nx,ny)

Melt mass flux (kg/m^2/s).

real(kind=wp), intent(in) :: areaT(nx,ny)

Cell area (m^2).

real(kind=wp), intent(out) :: vol_melt

Meltwater volume this step (m^3).

real(kind=wp), intent(out) :: area_open

Uncovered wet area (m^2).


Calls

proc~~cavity_mass_totals_impl~~CallsGraph proc~cavity_mass_totals_impl cavity_mass_totals_impl reduce reduce proc~cavity_mass_totals_impl->reduce

Called by

proc~~cavity_mass_totals_impl~~CalledByGraph proc~cavity_mass_totals_impl cavity_mass_totals_impl proc~ocean_cavity_mass_step ocean_cavity_mass_step proc~ocean_cavity_mass_step->proc~cavity_mass_totals_impl proc~run_stage run_stage proc~run_stage->proc~ocean_cavity_mass_step proc~run_stage_split run_stage_split proc~run_stage_split->proc~ocean_cavity_mass_step proc~ocean_dyn_step ocean_dyn_step proc~ocean_dyn_step->proc~run_stage proc~ocean_dyn_step_split ocean_dyn_step_split proc~ocean_dyn_step_split->proc~run_stage_split proc~engine_step engine_step proc~engine_step->proc~ocean_dyn_step proc~engine_step->proc~ocean_dyn_step_split proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~engine_step proc~rdb_ocean_step rdb_ocean_step proc~rdb_ocean_step->proc~engine_step

Variables

Type Visibility Attributes Name Initial
real(kind=wp), private :: acc_a
real(kind=wp), private :: acc_v
integer, private :: i
integer, private :: i_hi
integer, private :: i_lo
integer, private :: j
integer, private :: j_hi
integer, private :: j_lo

Source Code

   pure subroutine cavity_mass_totals_impl(nx, ny, nghost, dt_over_rho0, active, &
                                           wet_mask, cover_frac, melt, areaT, &
                                           vol_melt, area_open)
      !! The two INTERIOR integrals the mass budget and the compensation
      !! sink need, reduced on device in one pass:
      !!
      !!   `vol_melt`  — the meltwater volume (m^3) added this step,
      !!                 `sum(melt*dt/rho_0 * areaT)` over active columns;
      !!   `area_open` — the wet area (m^2) the ice does NOT cover.
      !!
      !! GHOSTS ARE EXCLUDED (`nghost+1 .. n-nghost`), exactly as
      !! `ocean_accumulate_mass_out` excludes them: the console's totals
      !! are interior integrals, so a source term that counted the halo
      !! would be measuring a different domain than the total it has to
      !! close.  The per-cell APPLY still runs over the whole array, like
      !! every other surface kernel — the halo exchange owns the ghosts.
      !!
      !! `melt*dt_over_rho0` is formed with the same scalar and in the
      !! same order as the apply kernel's `dh`, so the two agree to the
      !! last bit per cell and the residual is reduction round-off only.
      integer, intent(in) :: nx
         !! First dimension (ghosts included).
      integer, intent(in) :: ny
         !! Second dimension.
      integer, intent(in) :: nghost
         !! Halo width to exclude on every side.
      real(wp), intent(in) :: dt_over_rho0
         !! `dt/rho_0`.
      real(wp), intent(in) :: active(nx, ny)
         !! Composed solve mask.
      real(wp), intent(in) :: wet_mask(nx, ny)
         !! Static wet (1) / land (0) mask.
      real(wp), intent(in) :: cover_frac(nx, ny)
         !! Ice-cover fraction (v1 binary).
      real(wp), intent(in) :: melt(nx, ny)
         !! Melt mass flux (kg/m^2/s).
      real(wp), intent(in) :: areaT(nx, ny)
         !! Cell area (m^2).
      real(wp), intent(out) :: vol_melt
         !! Meltwater volume this step (m^3).
      real(wp), intent(out) :: area_open
         !! Uncovered wet area (m^2).
      integer :: i, j, i_lo, i_hi, j_lo, j_hi
      real(wp) :: acc_v, acc_a

      i_lo = nghost + 1
      i_hi = nx - nghost
      j_lo = nghost + 1
      j_hi = ny - nghost
      acc_v = 0.0_wp
      acc_a = 0.0_wp
      do concurrent(j=j_lo:j_hi, i=i_lo:i_hi) reduce(+:acc_v, acc_a)
         if (active(i, j) > 0.5_wp) then
            acc_v = acc_v + melt(i, j)*dt_over_rho0*areaT(i, j)
         end if
         if (wet_mask(i, j) > 0.5_wp .and. cover_frac(i, j) < 0.5_wp) then
            acc_a = acc_a + areaT(i, j)
         end if
      end do
      vol_melt = acc_v
      area_open = acc_a
   end subroutine cavity_mass_totals_impl