Skip to content

Incorrect area weights used in denominator of downsampled MMS diagnostics #979

@hdrake

Description

@hdrake

Downsampled diagnostics with MMS cell methods (i.e. "xh:mean yh:mean z_l:sum) are currently bugged, because incorrect weights are used in the weighted-averaging operation.

In the following lines, the weights are the product of a 3D mask array and a 2D area array.

elseif (method == MMP .or. method == MMS) then !e.g., T_advection_xy
do k=ks,ke ; do j=jsv_d,jev_d ; do i=isv_d,iev_d
i0 = isv_o+dl*(i-isv_d)
j0 = jsv_o+dl*(j-jsv_d)
ave = 0.0
total_weight = 0.0
do jj=j0,j0+dl-1 ; do ii=i0,i0+dl-1
! do ii=i0,i0+dl-1 ; do jj=j0,j0+dl-1
weight = mask(ii,jj,k) * diag_cs%G%areaT(ii,jj)
total_weight = total_weight + weight
ave = ave+field_in(ii,jj,k)*weight
enddo ; enddo
field_out(i,j,k) = ave / (total_weight+eps_area) !Avoid zero mask at all aggregating cells where ave=0.0
enddo ; enddo ; enddo

However, the 3D mask used to downsample the diagnostics seems to be a 2D wet mask that is simply projected downwards for all vertical levels:

subroutine diag_masks_set(G, nz, diag_cs)
type(ocean_grid_type), target, intent(in) :: G !< The ocean grid type.
integer, intent(in) :: nz !< The number of layers in the model's native grid.
type(diag_ctrl), pointer :: diag_cs !< A pointer to a type with many variables
!! used for diagnostics
! Local variables
integer :: k
! 2d masks point to the model masks since they are identical
diag_cs%mask2dT => G%mask2dT
diag_cs%mask2dBu => G%mask2dBu
diag_cs%mask2dCu => G%mask2dCu
diag_cs%mask2dCv => G%mask2dCv
! 3d native masks are needed by diag_manager but the native variables
! can only be masked 2d - for ocean points, all layers exists.
allocate(diag_cs%mask3dTL(G%isd:G%ied,G%jsd:G%jed,1:nz))
allocate(diag_cs%mask3dBL(G%IsdB:G%IedB,G%JsdB:G%JedB,1:nz))
allocate(diag_cs%mask3dCuL(G%IsdB:G%IedB,G%jsd:G%jed,1:nz))
allocate(diag_cs%mask3dCvL(G%isd:G%ied,G%JsdB:G%JedB,1:nz))
do k=1,nz
diag_cs%mask3dTL(:,:,k) = diag_cs%mask2dT(:,:)
diag_cs%mask3dBL(:,:,k) = diag_cs%mask2dBu(:,:)
diag_cs%mask3dCuL(:,:,k) = diag_cs%mask2dCu(:,:)
diag_cs%mask3dCvL(:,:,k) = diag_cs%mask2dCv(:,:)
enddo
allocate(diag_cs%mask3dTi(G%isd:G%ied,G%jsd:G%jed,1:nz+1))
allocate(diag_cs%mask3dBi(G%IsdB:G%IedB,G%JsdB:G%JedB,1:nz+1))
allocate(diag_cs%mask3dCui(G%IsdB:G%IedB,G%jsd:G%jed,1:nz+1))
allocate(diag_cs%mask3dCvi(G%isd:G%ied,G%JsdB:G%JedB,1:nz+1))
do k=1,nz+1
diag_cs%mask3dTi(:,:,k) = diag_cs%mask2dT(:,:)
diag_cs%mask3dBi(:,:,k) = diag_cs%mask2dBu(:,:)
diag_cs%mask3dCui(:,:,k) = diag_cs%mask2dCu(:,:)
diag_cs%mask3dCvi(:,:,k) = diag_cs%mask2dCv(:,:)
enddo
!Allocate and initialize the downsampled masks
call downsample_diag_masks_set(G, nz, diag_cs)
end subroutine diag_masks_set

In vertical coordinates that include masked land cells, such as below topography in depth coordinates, however, this 3D area weight array will incorrectly have non-zero areas for any cells that are "wet" according to the 2D mask but actually should be "dry" in 3D because they are under the sea floor.

Since the numerator in the weighted average is a product of the weight with an MMS diagnostic, which should be zero under the seafloor anyways, there is no problem there. The problem arises in the total weight used in the denominator, which will erroneously include all of these sub-seafloor areas in the total.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions