From a029b089d57c95bf2562a6628b3370886fde35eb Mon Sep 17 00:00:00 2001 From: Marshall Ward Date: Mon, 22 Jul 2019 13:24:46 -0400 Subject: [PATCH 1/2] KE_adv diag calculation using mask2d The KE_adv diagnostic is a sum of values multiplied by -1, which will assign a -0.0 value for zero-initialized states. This can lead to reproducibility problems for symmetric and nonsymmetric grids, since many intermediate calculations rely on masking of the u field and do not apply masks to subsequent steps. This can occur when a MPP domain is bordered by land, where calculations on the S and W boundaries of a symmetric grids are computed as if they are unmasked, and would be assigned a -0.0 value. For nonsymmetric grids, these values were never computed and would retain a +0.0 value. We resolve this by re-initalizing the KE_u and KE_v fields, since they are re-used as buffers for several diagnostics, and exclude masked points from the calculation. This ensures +0.0 values in any land boundaries across symmetric grids. If the masking is applied to other fields using `KE_u` and `KE_v`, then we may be able to remove the re-initialization step. While +/-0.0 are arithmetically identical in all cases, this fix will preserve bitwise reproducibility and is a step towards phasing out the `abs()` operation in the checksums. --- src/diagnostics/MOM_diagnostics.F90 | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/diagnostics/MOM_diagnostics.F90 b/src/diagnostics/MOM_diagnostics.F90 index 7997571404..d40d4577f1 100644 --- a/src/diagnostics/MOM_diagnostics.F90 +++ b/src/diagnostics/MOM_diagnostics.F90 @@ -994,12 +994,18 @@ subroutine calculate_energy_diagnostics(u, v, h, uh, vh, ADp, CDp, G, GV, CS) endif if (associated(CS%KE_adv)) then + ! NOTE: All terms in KE_adv are multipled by -1, which can easily produce + ! negative zeros and may signal a reproducibility issue over land. + ! We resolve this by re-initializing and only evaluating over water points. + KE_u(:,:) = 0. ; KE_v(:,:) = 0. do k=1,nz do j=js,je ; do I=Isq,Ieq - KE_u(I,j) = uh(I,j,k)*G%dxCu(I,j)*ADp%gradKEu(I,j,k) + if (G%mask2dCu(i,j) /= 0.) & + KE_u(I,j) = uh(I,j,k)*G%dxCu(I,j)*ADp%gradKEu(I,j,k) enddo ; enddo do J=Jsq,Jeq ; do i=is,ie - KE_v(i,J) = vh(i,J,k)*G%dyCv(i,J)*ADp%gradKEv(i,J,k) + if (G%mask2dCv(i,j) /= 0.) & + KE_v(i,J) = vh(i,J,k)*G%dyCv(i,J)*ADp%gradKEv(i,J,k) enddo ; enddo do j=js,je ; do i=is,ie KE_h(i,j) = -CS%KE(i,j,k) * G%IareaT(i,j) * & From 3467662c7587ff677962bf9041dfad0bff9f6774 Mon Sep 17 00:00:00 2001 From: Marshall Ward Date: Mon, 22 Jul 2019 13:39:05 -0400 Subject: [PATCH 2/2] Conditional registration of KPP_OBLdepth_original The diagnostic KPP_OBLdepth_original requires a nonzero CS%n_smooth value, but it is currently possible to register this diagnostic even when this parameter is unset. This patch only registers the diagnostic when n_smooth is defined. --- src/parameterizations/vertical/MOM_CVMix_KPP.F90 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/parameterizations/vertical/MOM_CVMix_KPP.F90 b/src/parameterizations/vertical/MOM_CVMix_KPP.F90 index 159a88958b..075e89426e 100644 --- a/src/parameterizations/vertical/MOM_CVMix_KPP.F90 +++ b/src/parameterizations/vertical/MOM_CVMix_KPP.F90 @@ -468,10 +468,12 @@ logical function KPP_init(paramFile, G, GV, US, diag, Time, CS, passive, Waves) ! CMOR names are placeholders; must be modified by time period ! for CMOR compliance. Diag manager will be used for omlmax and ! omldamax. - CS%id_OBLdepth_original = register_diag_field('ocean_model', 'KPP_OBLdepth_original', diag%axesT1, Time, & - 'Thickness of the surface Ocean Boundary Layer without smoothing calculated by [CVMix] KPP', 'meter', & - cmor_field_name='oml', cmor_long_name='ocean_mixed_layer_thickness_defined_by_mixing_scheme', & - cmor_units='m', cmor_standard_name='Ocean Mixed Layer Thickness Defined by Mixing Scheme') + if (CS%n_smooth > 0) then + CS%id_OBLdepth_original = register_diag_field('ocean_model', 'KPP_OBLdepth_original', diag%axesT1, Time, & + 'Thickness of the surface Ocean Boundary Layer without smoothing calculated by [CVMix] KPP', 'meter', & + cmor_field_name='oml', cmor_long_name='ocean_mixed_layer_thickness_defined_by_mixing_scheme', & + cmor_units='m', cmor_standard_name='Ocean Mixed Layer Thickness Defined by Mixing Scheme') + endif CS%id_BulkDrho = register_diag_field('ocean_model', 'KPP_BulkDrho', diag%axesTL, Time, & 'Bulk difference in density used in Bulk Richardson number, as used by [CVMix] KPP', 'kg/m3') CS%id_BulkUz2 = register_diag_field('ocean_model', 'KPP_BulkUz2', diag%axesTL, Time, &