From d0d051d2f55d06d35da160775a3ac105891a55c4 Mon Sep 17 00:00:00 2001 From: Robert Hallberg Date: Sat, 7 Dec 2024 08:44:49 -0500 Subject: [PATCH 1/2] +Refactor the spatial mean calculations Refactored the spatial mean calculations in the functions global_area_mean(), global_area_mean_u(), global_area_mean_v(), global_layer_mean(), global_volume_mean() and adjust_area_mean_to_zero() to work in rescaled units by making use of the unscale arguments to the reproducing_sum routines. Comments were also added to explain what the code does when both tmp_scale and unscale arguments are provided, which effectively acts as to allow for changes in the rescaled units. Global_area_integral() and global_mass_integral() were also similarly refactored, but with the added difference that when a tmp_scale argument is provided, the areas or masses in the integrals have units of [L2 A ~> m2 a] or [R Z L2 A ~> kg a] instead of the mixed units of [m2 A ~> m2 a] or [kg A ~> kg a]. As a result the code surrounding the 4 instances where global_area_integral or global_mass_integral were being called with tmp_scale arguments (in MOM.F90 and MOM_ice_shelf.F90) also had to be modified in this same commit. When the optional var argument is absent from a call to global_mass_integral() so that it is the mass itself that is returned, the values (if any) of scale, unscale and tmp_scale are ignored, but the presence of tmp_scale determines whether the mass is returned in [R Z L2 ~> kg] or [kg], consistent with the behavior that would have been obtained if var had been an array of nondimensional 1s. This commit also includes a rescaling in the units of the areaT_global and IareaT_global elements of the ocean_grid_type and dyn_horgrid_type to [L2 ~> m2] and [L-2 ~> m-2], respectively. Although the dyn_horgrid_type is shared between MOM6 and SIS2, these elements are not used in SIS2. A total of 12 rescaling factors were eliminated or moved into unscale arguments as a result of these changes. All answers are bitwise identical, but there are changes in the rescaled units of two elements each in two transparent types, and changes to the rescaling behavior of two publicly visible routines when they are called with tmp_scale arguments. --- src/core/MOM.F90 | 2 +- src/core/MOM_grid.F90 | 6 +- src/diagnostics/MOM_spatial_means.F90 | 398 +++++++++++------- src/framework/MOM_dyn_horgrid.F90 | 6 +- src/ice_shelf/MOM_ice_shelf.F90 | 6 +- .../MOM_shared_initialization.F90 | 2 +- 6 files changed, 259 insertions(+), 161 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index 8cfab91cfc..ad906fbdb4 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -4161,7 +4161,7 @@ subroutine get_ocean_stocks(CS, mass, heat, salt, on_PE_only) if (present(mass)) & mass = global_mass_integral(CS%h, CS%G, CS%GV, on_PE_only=on_PE_only) if (present(heat)) & - heat = CS%US%Q_to_J_kg*CS%tv%C_p * & + heat = CS%US%Q_to_J_kg*CS%US%RZL2_to_kg * CS%tv%C_p * & global_mass_integral(CS%h, CS%G, CS%GV, CS%tv%T, on_PE_only=on_PE_only, tmp_scale=CS%US%C_to_degC) if (present(salt)) & salt = 1.0e-3 * global_mass_integral(CS%h, CS%G, CS%GV, CS%tv%S, on_PE_only=on_PE_only, unscale=CS%US%S_to_ppt) diff --git a/src/core/MOM_grid.F90 b/src/core/MOM_grid.F90 index 10335de0a6..e0d456f9a3 100644 --- a/src/core/MOM_grid.F90 +++ b/src/core/MOM_grid.F90 @@ -177,9 +177,9 @@ module MOM_grid df_dx, & !< Derivative d/dx f (Coriolis parameter) at h-points [T-1 L-1 ~> s-1 m-1]. df_dy !< Derivative d/dy f (Coriolis parameter) at h-points [T-1 L-1 ~> s-1 m-1]. - ! These variables are global sums that are useful for 1-d diagnostics and should not be rescaled. - real :: areaT_global !< Global sum of h-cell area [m2] - real :: IareaT_global !< Global sum of inverse h-cell area (1/areaT_global) [m-2]. + ! These variables are global sums that are useful for 1-d diagnostics. + real :: areaT_global !< Global sum of h-cell area [L2 ~> m2] + real :: IareaT_global !< Global sum of inverse h-cell area (1/areaT_global) [L-2 ~> m-2]. type(unit_scale_type), pointer :: US => NULL() !< A dimensional unit scaling type diff --git a/src/diagnostics/MOM_spatial_means.F90 b/src/diagnostics/MOM_spatial_means.F90 index fe33e38a80..bc0b05b477 100644 --- a/src/diagnostics/MOM_spatial_means.F90 +++ b/src/diagnostics/MOM_spatial_means.F90 @@ -34,54 +34,61 @@ module MOM_spatial_means contains -!> Return the global area mean of a variable. This uses reproducing sums. +!> Return the global area mean of a variable, perhaps with a change of units. This uses reproducing sums. function global_area_mean(var, G, scale, tmp_scale, unscale) type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure - real, dimension(SZI_(G),SZJ_(G)), intent(in) :: var !< The variable to average in + real, dimension(SZI_(G),SZJ_(G)), intent(in) :: var !< The variable to average in arbitrary units [a], + !! or arbitrary rescaled units [A ~> a] if unscale + !! or tmp_scale is present !! arbitrary, possibly rescaled units [A ~> a] real, optional, intent(in) :: scale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) !! units to enable the use of the reproducing sums real, optional, intent(in) :: tmp_scale !< A temporary rescaling factor for the variable - !! that is reversed in the return value [a A-1 ~> 1] + !! that is reversed in the return value [a A-1 ~> 1], + !! or [b B-1 ~> 1] if unscale is also present. real, optional, intent(in) :: unscale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) - !! units to enable the use of the reproducing sums. + !! units to enable the use of the reproducing sums, or + !! a factor converting between rescaled units if + !! tmp_scale is also present [B A-1 ~> b a-1]. !! Here scale and unscale are synonymous, but unscale - !! is preferred and takes precedence if both are present. + !! is preferred and takes precedence. real :: global_area_mean ! The mean of the variable in arbitrary unscaled units [a] or scaled units [A ~> a] + ! or [B ~> b], depending on which optional arguments are provided ! Local variables - ! In the following comments, [A] is used to indicate the arbitrary, possibly rescaled units of the - ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums - real, dimension(SZI_(G),SZJ_(G)) :: tmpForSumming ! An unscaled cell integral [a m2] - real :: scalefac ! An overall scaling factor for the areas and variable [a m2 A-1 L-2 ~> 1] - real :: temp_scale ! A temporary scaling factor [a A-1 ~> 1] or [1] + ! In the following comments, [A ~> a] is used to indicate the arbitrary, possibly rescaled units of the + ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums. + ! [A ~> a] and [B ~> b] are the same units unless tmp_scale and unscale are both present. + real :: tmpForSumming(SZI_(G),SZJ_(G)) ! An unscaled cell integral in [a L2 ~> a m2] or a + ! scaled cell integral in [A L2 ~> a m2] or [B L2 ~> b m2] + real :: scalefac ! A scaling factor for the variable that is not reversed [a A-1 ~> 1] or [B A-1 ~> b a-1] or [1] + real :: temp_scale ! A temporary scaling factor [a A-1 ~> 1] or [b B-1 ~> 1] or [1] integer :: i, j, is, ie, js, je is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec temp_scale = 1.0 ; if (present(tmp_scale)) temp_scale = tmp_scale - scalefac = G%US%L_to_m**2*temp_scale - if (present(unscale)) then ; scalefac = scalefac * unscale - elseif (present(scale)) then ; scalefac = scalefac * scale ; endif + + scalefac = 1.0 + if (present(unscale)) then ; scalefac = unscale + elseif (present(scale)) then ; scalefac = scale ; endif tmpForSumming(:,:) = 0. do j=js,je ; do i=is,ie tmpForSumming(i,j) = var(i,j) * (scalefac * G%areaT(i,j) * G%mask2dT(i,j)) enddo ; enddo - global_area_mean = reproducing_sum(tmpForSumming) * G%IareaT_global - - if ((temp_scale /= 0.0) .and. (temp_scale /= 1.0)) & - global_area_mean = global_area_mean / temp_scale + global_area_mean = reproducing_sum(tmpForSumming, unscale=temp_scale*G%US%L_to_m**2) * G%IareaT_global end function global_area_mean !> Return the global area mean of a variable. This uses reproducing sums. function global_area_mean_v(var, G, tmp_scale) type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure - real, dimension(SZI_(G),SZJB_(G)), intent(in) :: var !< The variable to average in - !! arbitrary, possibly rescaled units [A ~> a] + real, dimension(SZI_(G),SZJB_(G)), intent(in) :: var !< The variable to average in arbitrary + !! units [a], or arbitrary rescaled units + !! [A ~> a] if tmp_scale is present real, optional, intent(in) :: tmp_scale !< A temporary rescaling factor for the !! variable that converts it back to unscaled !! (e.g., mks) units to enable the use of the @@ -92,10 +99,10 @@ function global_area_mean_v(var, G, tmp_scale) real :: global_area_mean_v ! The mean of the variable in the same arbitrary units as var [A ~> a] ! Local variables - ! In the following comments, [A] is used to indicate the arbitrary, possibly rescaled units of the + ! In the following comments, [A ~> a] is used to indicate the arbitrary, possibly rescaled units of the ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums - real, dimension(SZI_(G),SZJ_(G)) :: tmpForSumming ! An unscaled cell integral [a m2] - real :: scalefac ! An overall scaling factor for the areas and variable [a m2 A-1 L-2 ~> 1] + ! [A ~> a] and [B ~> b] are the same unless tmp_scale and unscale are both present. + real, dimension(SZI_(G),SZJ_(G)) :: tmpForSumming ! An unscaled cell integral [A L2 ~> a m2] real :: temp_scale ! A temporary scaling factor [a A-1 ~> 1] or [1] integer :: i, j, is, ie, js, je, isB, ieB, jsB, jeB @@ -103,25 +110,23 @@ function global_area_mean_v(var, G, tmp_scale) isB = G%iscB ; ieB = G%iecB ; jsB = G%jscB ; jeB = G%jecB temp_scale = 1.0 ; if (present(tmp_scale)) temp_scale = tmp_scale - scalefac = G%US%L_to_m**2*temp_scale tmpForSumming(:,:) = 0. do j=js,je ; do i=is,ie - tmpForSumming(i,j) = G%areaT(i,j) * scalefac * & + tmpForSumming(i,j) = G%areaT(i,j) * & (var(i,J) * G%mask2dCv(i,J) + var(i,J-1) * G%mask2dCv(i,J-1)) / & max(1.e-20, G%mask2dCv(i,J)+G%mask2dCv(i,J-1)) enddo ; enddo - global_area_mean_v = reproducing_sum(tmpForSumming) * G%IareaT_global - if ((temp_scale /= 0.0) .and. (temp_scale /= 1.0)) & - global_area_mean_v = global_area_mean_v / temp_scale + global_area_mean_v = reproducing_sum(tmpForSumming, unscale=G%US%L_to_m**2*temp_scale) * G%IareaT_global end function global_area_mean_v !> Return the global area mean of a variable on U grid. This uses reproducing sums. function global_area_mean_u(var, G, tmp_scale) type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure - real, dimension(SZIB_(G),SZJ_(G)), intent(in) :: var !< The variable to average in - !! arbitrary, possibly rescaled units [A ~> a] + real, dimension(SZIB_(G),SZJ_(G)), intent(in) :: var !< The variable to average in arbitrary + !! units [a], or arbitrary rescaled units + !! [A ~> a] if tmp_scale is present real, optional, intent(in) :: tmp_scale !< A temporary rescaling factor for the !! variable that converts it back to unscaled !! (e.g., mks) units to enable the use of the @@ -131,10 +136,9 @@ function global_area_mean_u(var, G, tmp_scale) real :: global_area_mean_u ! The mean of the variable in the same arbitrary units as var [A ~> a] ! Local variables - ! In the following comments, [A] is used to indicate the arbitrary, possibly rescaled units of the + ! In the following comments, [A ~> a] is used to indicate the arbitrary, possibly rescaled units of the ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums - real, dimension(SZI_(G),SZJ_(G)) :: tmpForSumming ! An unscaled cell integral [a m2] - real :: scalefac ! An overall scaling factor for the areas and variable [a m2 A-1 L-2 ~> 1] + real, dimension(SZI_(G),SZJ_(G)) :: tmpForSumming ! An unscaled cell integral [A L2 ~> a m2] real :: temp_scale ! A temporary scaling factor [a A-1 ~> 1] or [1] integer :: i, j, is, ie, js, je, isB, ieB, jsB, jeB @@ -142,52 +146,75 @@ function global_area_mean_u(var, G, tmp_scale) isB = G%iscB ; ieB = G%iecB ; jsB = G%jscB ; jeB = G%jecB temp_scale = 1.0 ; if (present(tmp_scale)) temp_scale = tmp_scale - scalefac = G%US%L_to_m**2*temp_scale tmpForSumming(:,:) = 0. do j=js,je ; do i=is,ie - tmpForSumming(i,j) = G%areaT(i,j) * scalefac * & + tmpForSumming(i,j) = G%areaT(i,j) * & (var(I,j) * G%mask2dCu(I,j) + var(I-1,j) * G%mask2dCu(I-1,j)) / & max(1.e-20, G%mask2dCu(I,j)+G%mask2dCu(I-1,j)) enddo ; enddo - global_area_mean_u = reproducing_sum(tmpForSumming) * G%IareaT_global - if ((temp_scale /= 0.0) .and. (temp_scale /= 1.0)) & - global_area_mean_u = global_area_mean_u / temp_scale + global_area_mean_u = reproducing_sum(tmpForSumming, unscale=G%US%L_to_m**2*temp_scale) * G%IareaT_global end function global_area_mean_u -!> Return the global area integral of a variable, by default using the masked area from the -!! grid, but an alternate could be used instead. This uses reproducing sums. +!> Return the global area integral of a variable using reproducing sums, perhaps with a change of units. +!! By default the integral uses the masked area from the grid, but an alternate could be used instead. +!! The presence of the optional tmp_scale argument determines whether the returned value is in scaled +!! (if it is present) or unscaled units for both the variable itself and for the area in the integral. function global_area_integral(var, G, scale, area, tmp_scale, unscale) type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure - real, dimension(SZI_(G),SZJ_(G)), intent(in) :: var !< The variable to integrate in - !! arbitrary, possibly rescaled units [A ~> a] + real, dimension(SZI_(G),SZJ_(G)), intent(in) :: var !< The variable to integrate in arbitrary units [a], + !! or arbitrary rescaled units [A ~> a] if unscale + !! or tmp_scale is present real, optional, intent(in) :: scale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) !! units to enable the use of the reproducing sums real, dimension(SZI_(G),SZJ_(G)), optional, intent(in) :: area !< The alternate area to use, including !! any required masking [L2 ~> m2]. - real, optional, intent(in) :: tmp_scale !< A temporary rescaling factor for the - !! variable that is reversed in the return value [a A-1 ~> 1] + real, optional, intent(in) :: tmp_scale !< A temporary rescaling factor for the variable + !! that is reversed in the return value [a A-1 ~> 1], + !! or [b B-1 ~> 1] if unscale is also present. real, optional, intent(in) :: unscale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) - !! units to enable the use of the reproducing sums. + !! units to enable the use of the reproducing sums, or + !! a factor converting between rescaled units if + !! tmp_scale is also present [B A-1 ~> b a-1]. !! Here scale and unscale are synonymous, but unscale !! is preferred and takes precedence if both are present. real :: global_area_integral !< The returned area integral, usually in the units of var times an area, - !! [a m2] or [A m2 ~> a m2] depending on which optional arguments are provided + !! [a m2] or [A L2 ~> a m2] or [B L2 ~> b m2], depending on which optional + !! arguments are provided ! Local variables - ! In the following comments, [A] is used to indicate the arbitrary, possibly rescaled units of the - ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums - real, dimension(SZI_(G),SZJ_(G)) :: tmpForSumming ! An unscaled cell integral [a m2] - real :: scalefac ! An overall scaling factor for the areas and variable, perhaps in [m2 a A-1 L-2 ~> 1] - real :: temp_scale ! A temporary scaling factor [a A-1 ~> 1] or [1] + ! In the following comments, [A ~> a] is used to indicate the arbitrary, possibly rescaled units of the + ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums. + ! [A ~> a] and [B ~> b] are the same units unless tmp_scale and unscale are both present. + real, dimension(SZI_(G),SZJ_(G)) :: tmpForSumming ! An unscaled cell integral in [a m2] or + ! a scaled cell integral in [B L2 ~> b m2] or other units as indicated below + real :: scalefac ! An overall scaling factor for the areas and variable, in units of [a m2 A-1 L-2 ~> 1] + ! or [1] or [B m2 A-1 L-2 ~> b a-1] or [B A-1 ~> b a-1] depending on which + ! optional arguments are present. + !_______________________________________________________________________________________________ + ! Table of units of scalefac and tmpForSumming, depending on the presence of optional arguments | + !_______________________________________________________________________________________________| + ! present(tmp_scale) | present(unscale) | scalefac units | tmpForSumming units | + !____________________|__________________|_________________________|_____________________________! + ! True | True | [B A-1 ~> b a-1] | [B L2 ~> b m2] | + ! True | False | [1] | [A L2 ~> a m2] | + ! False | True | [a m2 A-1 L-2 ~> b a-1] | [a m2] | + ! False | False | [m2 L-2 ~> 1] | [a m2] | + !____________________|__________________|_________________________|_____________________________! + real :: temp_scale ! A temporary scaling factor [a m2 L-2 A-1 ~> 1] or [b m2 L-2 B-1 ~> 1] or [1] integer :: i, j, is, ie, js, je is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec - temp_scale = 1.0 ; if (present(tmp_scale)) temp_scale = tmp_scale - scalefac = G%US%L_to_m**2*temp_scale + if (present(tmp_scale)) then + temp_scale = G%US%L_to_m**2 * tmp_scale ! Units of [a m2 A-1 L-2 ~> 1] or [b m2 B-1 L-2 ~> 1] + scalefac = 1.0 + else + temp_scale = 1.0 + scalefac = G%US%L_to_m**2 + endif if (present(unscale)) then ; scalefac = scalefac * unscale elseif (present(scale)) then ; scalefac = scalefac * scale ; endif @@ -202,10 +229,7 @@ function global_area_integral(var, G, scale, area, tmp_scale, unscale) enddo ; enddo endif - global_area_integral = reproducing_sum(tmpForSumming) - - if ((temp_scale /= 0.0) .and. (temp_scale /= 1.0)) & - global_area_integral = global_area_integral / temp_scale + global_area_integral = reproducing_sum(tmpForSumming, unscale=temp_scale) end function global_area_integral @@ -213,55 +237,87 @@ end function global_area_integral function global_layer_mean(var, h, G, GV, scale, tmp_scale, unscale) type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: var !< The variable to average in - !! arbitrary, possibly rescaled units [A ~> a] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: var !< The variable to average in arbitrary units [a], + !! or arbitrary rescaled units [A ~> a] if unscale + !! or tmp_scale is present real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2] real, optional, intent(in) :: scale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) !! units to enable the use of the reproducing sums real, optional, intent(in) :: tmp_scale !< A temporary rescaling factor for the - !! variable that is reversed in the return value [a A-1 ~> 1] + !! variable for use in the reproducing sums + !! that is reversed in the return value [a A-1 ~> 1], + !! or [b B-1 ~> 1] if unscale is also present. real, optional, intent(in) :: unscale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) - !! units to enable the use of the reproducing sums. + !! units to enable the use of the reproducing sums, or + !! a factor converting between rescaled units if + !! tmp_scale is also present [B A-1 ~> b a-1]. !! Here scale and unscale are synonymous, but unscale !! is preferred and takes precedence. - real, dimension(SZK_(GV)) :: global_layer_mean !< The mean of the variable in the arbitrary scaled [A] - !! or unscaled [a] units of var, depending on which optional - !! arguments are provided + real, dimension(SZK_(GV)) :: global_layer_mean !< The mean of the variable in the arbitrary scaled [A ~> a] + !! or [B ~> b] or unscaled [a] units of var, depending on which + !! optional arguments are provided ! Local variables - ! In the following comments, [A] is used to indicate the arbitrary, possibly rescaled units of the + ! In the following comments, [A ~> a] is used to indicate the arbitrary, possibly rescaled units of the ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums - real, dimension(G%isc:G%iec,G%jsc:G%jec,SZK_(GV)) :: tmpForSumming ! An unscaled cell integral [a m3] or [a kg] - real, dimension(G%isc:G%iec,G%jsc:G%jec,SZK_(GV)) :: weight ! The volume or mass of each cell, depending on - ! whether the model is Boussinesq, used as a weight [m3] or [kg] - type(EFP_type), dimension(2*SZK_(GV)) :: laysums - real, dimension(SZK_(GV)) :: global_temp_scalar ! The global integral of the tracer in each layer [a m3] or [a kg] - real, dimension(SZK_(GV)) :: global_weight_scalar ! The global integral of the volume or mass of each - ! layer [m3] or [kg] - real :: temp_scale ! A temporary scaling factor [a A-1 ~> 1] or [1] - real :: scalefac ! A scaling factor for the variable [a A-1 ~> 1] + real :: tmpForSumming(G%isc:G%iec,G%jsc:G%jec,SZK_(GV)) ! An unscaled cell integral in [L2 a m ~> a m3] or + ! [L2 a kg m-2 ~> a kg] or a scaled cell integral in + ! [L2 B m ~> b m3] or [L2 B m ~> b m3] or other units + ! as indicated the table below. + real :: weight(G%isc:G%iec,G%jsc:G%jec,SZK_(GV)) ! The volume or mass of each cell, depending on whether + ! the model is Boussinesq, used as a weight [L2 m ~> m3] + ! or [L2 kg m-2 ~> kg] + real :: scalefac ! A scaling factor for the variable [a A-1 ~> 1] or [B A-1 ~> b a-1] or [1] + !__________________________________________________________________________________________________ + ! Units of weight, scalefac and tmpForSumming, depending on the presence of optional arguments | + !_________________________________________________________________________________________________| + ! Boussinesq | tmp_scale | unscale | weight units | scalefac units | tmpForSumming units | + ! | present | present | | | | + !____________|___________|_________|___________________|__________________|_______________________! + ! True | True | True | [L2 m ~> m3] | [B A-1 ~> b a-1] | [B L2 m ~> b m3] | + ! True | True | False | [L2 m ~> m3] | [1] | [A L2 m ~> a m3] | + ! True | False | True | [L2 m ~> m3] | [a A-1 ~> 1] | [L2 a m ~> a m3] | + ! True | False | False | [L2 m ~> m3] | [1] | [L2 a m ~> a m3] | + ! False | True | True | [L2 kg m-2 ~> kg] | [B A-1 ~> b a-1] | [B L2 kg m-2 ~> b kg] | + ! False | True | False | [L2 kg m-2 ~> kg] | [1] | [A L2 kg m-2 ~> a kg] | + ! False | False | True | [L2 kg m-2 ~> kg] | [a A-1 ~> 1] | [L2 a kg m-2 ~> a kg] | + ! False | False | False | [L2 kg m-2 ~> kg] | [1] | [L2 a kg m-2 ~> a kg] | + !____________|___________|_________|___________________|__________________|_______________________! + type(EFP_type) :: laysums(2*SZK_(GV)) ! A vector of sums with heterogeneous meanings, with the first + ! half being the tracer integrals in [b m3] or [b kg] and the + ! second half being the summed weights in [m3] or [kg] + real :: global_temp_scalar ! The global integral of the tracer over all + ! layers [L2 a m ~> a m3] or [L2 a kg m-2 ~> a kg] + real :: global_weight_scalar ! The global integral of the volume or mass over all + ! layers [L2 m ~> m3] or [L2 kg m-2 ~> kg] + real :: temp_scale ! A temporary scaling factor [a A-1 ~> 1] or [b B-1 ~> 1] or [1] integer :: i, j, k, is, ie, js, je, nz is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke temp_scale = 1.0 ; if (present(tmp_scale)) temp_scale = tmp_scale - scalefac = temp_scale - if (present(unscale)) then ; scalefac = unscale * temp_scale - elseif (present(scale)) then ; scalefac = scale * temp_scale ; endif + + scalefac = 1.0 + if (present(unscale)) then ; scalefac = unscale + elseif (present(scale)) then ; scalefac = scale ; endif tmpForSumming(:,:,:) = 0. ; weight(:,:,:) = 0. do k=1,nz ; do j=js,je ; do i=is,ie - weight(i,j,k) = (GV%H_to_MKS * h(i,j,k)) * (G%US%L_to_m**2*G%areaT(i,j) * G%mask2dT(i,j)) + weight(i,j,k) = (GV%H_to_MKS * h(i,j,k)) * (G%areaT(i,j) * G%mask2dT(i,j)) tmpForSumming(i,j,k) = scalefac * var(i,j,k) * weight(i,j,k) enddo ; enddo ; enddo - global_temp_scalar = reproducing_sum(tmpForSumming, EFP_lay_sums=laysums(1:nz), only_on_PE=.true.) - global_weight_scalar = reproducing_sum(weight, EFP_lay_sums=laysums(nz+1:2*nz), only_on_PE=.true.) + global_temp_scalar = reproducing_sum(tmpForSumming, EFP_lay_sums=laysums(1:nz), only_on_PE=.true., & + unscale=temp_scale*G%US%L_to_m**2) + global_weight_scalar = reproducing_sum(weight, EFP_lay_sums=laysums(nz+1:2*nz), only_on_PE=.true., & + unscale=G%US%L_to_m**2) call EFP_sum_across_PEs(laysums, 2*nz) + ! Note that temp_scale appears in the denominator here because the variables returned via the + ! EFP_lay_sums arguments to reproducing sums stay in unscaled mks units. do k=1,nz - global_layer_mean(k) = EFP_to_real(laysums(k)) / (temp_scale * EFP_to_real(laysums(nz+k))) + global_layer_mean(k) = EFP_to_real(laysums(k)) / (temp_scale*EFP_to_real(laysums(nz+k))) enddo end function global_layer_mean @@ -271,105 +327,147 @@ function global_volume_mean(var, h, G, GV, scale, tmp_scale, unscale) type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(in) :: var !< The variable being averaged in - !! arbitrary, possibly rescaled units [A ~> a] + intent(in) :: var !< The variable to average in arbitrary units [a], + !! or arbitrary rescaled units [A ~> a] if unscale + !! or tmp_scale is present real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2] real, optional, intent(in) :: scale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) !! units to enable the use of the reproducing sums real, optional, intent(in) :: tmp_scale !< A temporary rescaling factor for the - !! variable that is reversed in the return value [a A-1 ~> 1] + !! variable that is reversed in the return value [a A-1 ~> 1], + !! or [b B-1 ~> 1] if unscale is also present. real, optional, intent(in) :: unscale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) - !! units to enable the use of the reproducing sums. + !! units to enable the use of the reproducing sums, or + !! a factor converting between rescaled units if + !! tmp_scale is also present [B A-1 ~> b a-1]. !! Here scale and unscale are synonymous, but unscale !! is preferred and takes precedence if both are present. - real :: global_volume_mean !< The thickness-weighted average of var in the arbitrary scaled [A] or + real :: global_volume_mean !< The thickness-weighted average of var in the arbitrary scaled [A ~> a] or [B ~> b] or !! unscaled [a] units of var, depending on which optional arguments are provided ! Local variables - ! In the following comments, [A] is used to indicate the arbitrary, possibly rescaled units of the + ! In the following comments, [A ~> a] is used to indicate the arbitrary, possibly rescaled units of the ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums - real :: temp_scale ! A temporary scaling factor [a A-1 ~> 1] or [1] - real :: scalefac ! A scaling factor for the variable [a A-1 ~> 1] - real :: weight_here ! The volume or mass of a grid cell [m3] or [kg] - real, dimension(SZI_(G),SZJ_(G)) :: tmpForSumming ! The volume integral of the variable in a column [a m3] or [a kg] - real, dimension(SZI_(G),SZJ_(G)) :: sum_weight ! The volume or mass of each column of water [m3] or [kg] + ! [A ~> a] and [B ~> b] are the same units unless tmp_scale and unscale are both present. + real :: temp_scale ! A temporary scaling factor [a A-1 ~> 1] or [b B-1 ~> 1] or [1] + real :: scalefac ! A scaling factor for the variable [a A-1 ~> 1] or [B A-1 ~> b a-1] or [1] + real :: weight_here ! The volume or mass of a grid cell [L2 m ~> m3] or [L2 kg m-2 ~> kg] + real, dimension(SZI_(G),SZJ_(G)) :: tmpForSumming ! The volume or mass integral of the variable in a column + ! [B L2 m ~> b m3] or [B L2 kg m-2 ~> b kg] or + ! [L2 a m ~> a m3] or [L2 a kg m-2 ~> a kg] + real, dimension(SZI_(G),SZJ_(G)) :: sum_weight ! The volume or mass of each column of water + ! [L2 m ~> m3] or [L2 kg m-2 ~> kg] integer :: i, j, k, is, ie, js, je, nz is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke temp_scale = 1.0 ; if (present(tmp_scale)) temp_scale = tmp_scale - scalefac = temp_scale - if (present(unscale)) then ; scalefac = temp_scale * unscale - elseif (present(scale)) then ; scalefac = temp_scale * scale ; endif + + scalefac = 1.0 + if (present(unscale)) then ; scalefac = unscale + elseif (present(scale)) then ; scalefac = scale ; endif tmpForSumming(:,:) = 0. ; sum_weight(:,:) = 0. do k=1,nz ; do j=js,je ; do i=is,ie - weight_here = (GV%H_to_MKS * h(i,j,k)) * (G%US%L_to_m**2*G%areaT(i,j) * G%mask2dT(i,j)) + weight_here = (GV%H_to_MKS * h(i,j,k)) * (G%areaT(i,j) * G%mask2dT(i,j)) tmpForSumming(i,j) = tmpForSumming(i,j) + scalefac * var(i,j,k) * weight_here sum_weight(i,j) = sum_weight(i,j) + weight_here enddo ; enddo ; enddo - global_volume_mean = (reproducing_sum(tmpForSumming)) / & - (temp_scale * reproducing_sum(sum_weight)) + global_volume_mean = (reproducing_sum(tmpForSumming, unscale=temp_scale*G%US%L_to_m**2)) / & + (reproducing_sum(sum_weight, unscale=G%US%L_to_m**2)) end function global_volume_mean -!> Find the global mass-weighted integral of a variable. This uses reproducing sums. +!> Find the global mass-weighted integral of a variable. The presence of the optional tmp_scale +!! argument determines whether the returned value is in scaled (if it is present) or unscaled units +!! for both the variable itself and for the mass in the integral. This function uses reproducing sums. function global_mass_integral(h, G, GV, var, on_PE_only, scale, tmp_scale, unscale) type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - optional, intent(in) :: var !< The variable being integrated in - !! arbitrary, possibly rescaled units [A ~> a] + optional, intent(in) :: var !< The variable to integrate in arbitrary units [a], + !! or arbitrary rescaled units [A ~> a] if unscale + !! or tmp_scale is present logical, optional, intent(in) :: on_PE_only !< If present and true, the sum is only done !! on the local PE, and it is _not_ order invariant. real, optional, intent(in) :: scale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) !! units to enable the use of the reproducing sums - real, optional, intent(in) :: tmp_scale !< A temporary rescaling factor for the - !! variable that is reversed in the return value [a A-1 ~> 1] + real, optional, intent(in) :: tmp_scale !< A temporary rescaling factor for the variable + !! that is reversed in the return value [a A-1 ~> 1], + !! or [b B-1 ~> 1] if unscale is also present. real, optional, intent(in) :: unscale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) - !! units to enable the use of the reproducing sums. + !! units to enable the use of the reproducing sums, or + !! a factor converting between rescaled units if + !! tmp_scale is also present [B A-1 ~> b a-1]. !! Here scale and unscale are synonymous, but unscale !! is preferred and takes precedence if both are present. - real :: global_mass_integral !< The mass-weighted integral of var (or 1) in - !! kg times the arbitrary units of var [kg a] or [kg A ~> kg a] + real :: global_mass_integral !< The mass-weighted integral of var (or 1) in kg times the arbitrary + !! units of var [kg a] or in [R Z L2 A ~> kg a] if tmp_scale is present + !! or [R Z L2 B ~> kg b] if both unscale and tmp_scale are present ! Local variables - ! In the following comments, [A] is used to indicate the arbitrary, possibly rescaled units of the + ! In the following comments, [A ~> a] is used to indicate the arbitrary, possibly rescaled units of the ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums - real, dimension(SZI_(G),SZJ_(G)) :: tmpForSumming ! The mass-weighted integral of the variable in a column [kg a] - real :: scalefac ! An overall scaling factor for the cell mass and variable [a kg A-1 H-1 L-2 ~> kg m-3 or 1] - real :: temp_scale ! A temporary scaling factor [1] or [a A-1 ~> 1] + ! [A ~> a] and [B ~> b] are the same units unless tmp_scale and unscale are both present. + real :: tmpForSumming(SZI_(G),SZJ_(G)) ! The mass-weighted integral of the variable in a column in + ! [kg a] or [kg] or if tmp_scale is present in [B R Z L2 ~> kg b] or + ! [A R Z L2 !> kg m] or [R Z L2 ~> kg] + real :: scalefac ! An overall scaling factor for the cell mass and variable in [a kg A-1 R-1 Z-1 L-2 ~> 1] + ! or [kg R-1 Z-1 L-2 ~> 1] or [1] or [B A-1 ~> b a-1] if tmp_scale is present. + real :: temp_scale ! A temporary scaling factor [1] or if tmp_scale is present this could be in + ! [kg a R-1 Z-1 L-2 A-1 ~> 1] or [kg b R-1 Z-1 L-2 B-1 ~> 1] or [kg R-1 Z-1 L-2 ~> 1] + !_______________________________________________________________________________________ + ! Units of scalefac and tmpForSumming, depending on the presence of optional arguments | + !______________________________________________________________________________________| + ! var | tmp_scale | unscale | scalefac units | tmpForSumming units | + ! present | present | present | | | + !_________|___________|_________|_____________________________|________________________! + ! True | True | True | [B A-1 ~> b a-1] | [B R Z L2 ~> b kg] | + ! True | True | False | [1] | [A R Z L2 ~> a kg] | + ! True | False | True | [a kg A-1 R-1 Z-1 L-2 ~> 1] | [a kg] | + ! True | False | False | [kg R-1 Z-1 L-2 ~> 1] | [a kg] | + ! False | True | either | [1] | [R Z L2 ~> kg] | + ! False | False | either | [kg R-1 Z-1 L-2 ~> 1] | [kg] | + !_________|___________|_________|_____________________________|________________________! logical :: global_sum ! If true do the sum globally, but if false only do the sum on the current PE. integer :: i, j, k, is, ie, js, je, nz is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke - temp_scale = 1.0 ; if (present(tmp_scale)) temp_scale = tmp_scale - scalefac = G%US%L_to_m**2*temp_scale - if (present(unscale)) then ; scalefac = scalefac * unscale - elseif (present(scale)) then ; scalefac = scalefac * scale ; endif - tmpForSumming(:,:) = 0.0 + if (present(tmp_scale)) then + temp_scale = G%US%RZL2_to_kg * tmp_scale + if (.not.present(var)) temp_scale = G%US%RZL2_to_kg + scalefac = 1.0 + else + temp_scale = 1.0 + scalefac = G%US%RZL2_to_kg + endif + if (present(var)) then + if (present(unscale)) then ; scalefac = scalefac * unscale + elseif (present(scale)) then ; scalefac = scalefac * scale ; endif + endif + tmpForSumming(:,:) = 0.0 if (present(var)) then do k=1,nz ; do j=js,je ; do i=is,ie tmpForSumming(i,j) = tmpForSumming(i,j) + var(i,j,k) * & - ((GV%H_to_kg_m2 * h(i,j,k)) * (scalefac*G%areaT(i,j) * G%mask2dT(i,j))) + ((GV%H_to_RZ * h(i,j,k)) * (scalefac*G%areaT(i,j) * G%mask2dT(i,j))) enddo ; enddo ; enddo else do k=1,nz ; do j=js,je ; do i=is,ie tmpForSumming(i,j) = tmpForSumming(i,j) + & - ((GV%H_to_kg_m2 * h(i,j,k)) * (scalefac*G%areaT(i,j) * G%mask2dT(i,j))) + ((GV%H_to_RZ * h(i,j,k)) * (scalefac*G%areaT(i,j) * G%mask2dT(i,j))) enddo ; enddo ; enddo endif global_sum = .true. ; if (present(on_PE_only)) global_sum = .not.on_PE_only if (global_sum) then - global_mass_integral = reproducing_sum(tmpForSumming) + global_mass_integral = reproducing_sum(tmpForSumming, unscale=temp_scale) else global_mass_integral = 0.0 do j=js,je ; do i=is,ie @@ -377,9 +475,6 @@ function global_mass_integral(h, G, GV, var, on_PE_only, scale, tmp_scale, unsca enddo ; enddo endif - if ((temp_scale /= 0.0) .and. (temp_scale /= 1.0)) & - global_mass_integral = global_mass_integral / temp_scale - end function global_mass_integral !> Find the global mass-weighted order invariant integral of a variable in mks units, @@ -390,13 +485,14 @@ function global_mass_int_EFP(h, G, GV, var, on_PE_only, scale, unscale) real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - optional, intent(in) :: var !< The variable being integrated in - !! arbitrary, possibly rescaled units [A ~> a] + optional, intent(in) :: var !< The variable to integrate in arbitrary units [a], + !! or arbitrary rescaled units [A ~> a] if unscale + !! is present logical, optional, intent(in) :: on_PE_only !< If present and true, the sum is only done !! on the local PE, but it is still order invariant. real, optional, intent(in) :: scale !< A rescaling factor for the variable [a A-1 ~> 1] - !! that converts it back to unscaled (e.g., mks) - !! units to enable the use of the reproducing sums + !! that converts it back to unscaled (e.g., mks) + !! units to enable the use of the reproducing sums real, optional, intent(in) :: unscale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) !! units to enable the use of the reproducing sums. @@ -406,9 +502,9 @@ function global_mass_int_EFP(h, G, GV, var, on_PE_only, scale, unscale) !! kg times the arbitrary units of var [kg a] ! Local variables - ! In the following comments, [A] is used to indicate the arbitrary, possibly rescaled units of the + ! In the following comments, [A ~> a] is used to indicate the arbitrary, possibly rescaled units of the ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums - real, dimension(SZI_(G),SZJ_(G)) :: tmpForSum ! The mass-weighted integral of the variable in a column [kg a] + real :: tmpForSum(SZI_(G),SZJ_(G)) ! The mass-weighted integral of the variable in a column [kg a] or [kg] real :: scalefac ! An overall scaling factor for the cell mass and variable [a kg A-1 H-1 L-2 ~> kg m-3 or 1] integer :: i, j, k, is, ie, js, je, nz, isr, ier, jsr, jer @@ -440,9 +536,10 @@ end function global_mass_int_EFP !> Determine the global mean of a field along rows of constant i, returning it !! in a 1-d array using the local indexing. This uses reproducing sums. subroutine global_i_mean(array, i_mean, G, mask, scale, tmp_scale, unscale) - type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure - real, dimension(SZI_(G),SZJ_(G)), intent(in) :: array !< The variable being averaged in - !! arbitrary, possibly rescaled units [A ~> a] + type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure + real, dimension(SZI_(G),SZJ_(G)), intent(in) :: array !< The variable to integrate in arbitrary units [a], + !! or arbitrary rescaled units [A ~> a] if unscale + !! is present real, dimension(SZJ_(G)), intent(out) :: i_mean !< Global mean of array along its i-axis [a] or [A ~> a] real, dimension(SZI_(G),SZJ_(G)), & optional, intent(in) :: mask !< An array used for weighting the i-mean [nondim] @@ -458,7 +555,7 @@ subroutine global_i_mean(array, i_mean, G, mask, scale, tmp_scale, unscale) !! is preferred and takes precedence if both are present. ! Local variables - ! In the following comments, [A] is used to indicate the arbitrary, possibly rescaled units of the + ! In the following comments, [A ~> a] is used to indicate the arbitrary, possibly rescaled units of the ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums type(EFP_type), allocatable, dimension(:) :: asum ! The masked sum of the variable in each row [a] type(EFP_type), allocatable, dimension(:) :: mask_sum ! The sum of the mask values in each row [nondim] @@ -540,9 +637,10 @@ end subroutine global_i_mean !> Determine the global mean of a field along rows of constant j, returning it !! in a 1-d array using the local indexing. This uses reproducing sums. subroutine global_j_mean(array, j_mean, G, mask, scale, tmp_scale, unscale) - type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure - real, dimension(SZI_(G),SZJ_(G)), intent(in) :: array !< The variable being averaged in - !! arbitrary, possibly rescaled units [A ~> a] + type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure + real, dimension(SZI_(G),SZJ_(G)), intent(in) :: array !< The variable to integrate in arbitrary units [a], + !! or arbitrary rescaled units [A ~> a] if unscale + !! is present real, dimension(SZI_(G)), intent(out) :: j_mean !< Global mean of array along its j-axis [a] or [A ~> a] real, dimension(SZI_(G),SZJ_(G)), & optional, intent(in) :: mask !< An array used for weighting the j-mean [nondim] @@ -558,7 +656,7 @@ subroutine global_j_mean(array, j_mean, G, mask, scale, tmp_scale, unscale) !! is preferred and takes precedence if both are present. ! Local variables - ! In the following comments, [A] is used to indicate the arbitrary, possibly rescaled units of the + ! In the following comments, [A ~> a] is used to indicate the arbitrary, possibly rescaled units of the ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums type(EFP_type), allocatable, dimension(:) :: asum ! The masked sum of the variable in each row [a] type(EFP_type), allocatable, dimension(:) :: mask_sum ! The sum of the mask values in each row [nondim] @@ -640,8 +738,9 @@ end subroutine global_j_mean !> Adjust 2d array such that area mean is zero without moving the zero contour subroutine adjust_area_mean_to_zero(array, G, scaling, unit_scale, unscale) type(ocean_grid_type), intent(in) :: G !< Grid structure - real, dimension(SZI_(G),SZJ_(G)), intent(inout) :: array !< 2D array to be adjusted in - !! arbitrary, possibly rescaled units [A ~> a] + real, dimension(SZI_(G),SZJ_(G)), intent(inout) :: array !< 2D array to be adjusted in arbitrary units [a], + !! or arbitrary rescaled units [A ~> a] if unscale + !! is present real, optional, intent(out) :: scaling !< The scaling factor used [nondim] real, optional, intent(in) :: unit_scale !< A rescaling factor for the variable [a A-1 ~> 1] !! that converts it back to unscaled (e.g., mks) @@ -652,13 +751,14 @@ subroutine adjust_area_mean_to_zero(array, G, scaling, unit_scale, unscale) !! Here unit_scale and unscale are synonymous, but unscale !! is preferred and takes precedence if both are present. ! Local variables - ! In the following comments, [A] is used to indicate the arbitrary, possibly rescaled units of the + ! In the following comments, [A ~> a] is used to indicate the arbitrary, possibly rescaled units of the ! input array while [a] indicates the unscaled (e.g., mks) units that can be used with the reproducing sums - real, dimension(G%isc:G%iec, G%jsc:G%jec) :: posVals, negVals ! The positive or negative values in a cell or 0 [a] - real, dimension(G%isc:G%iec, G%jsc:G%jec) :: areaXposVals, areaXnegVals ! The cell area integral of the values [m2 a] + real :: posVals(G%isc:G%iec, G%jsc:G%jec) ! The positive values in a cell or 0 [A ~> a] + real :: negVals(G%isc:G%iec, G%jsc:G%jec) ! The negative values in a cell or 0 [A ~> a] + real :: areaXposVals(G%isc:G%iec, G%jsc:G%jec) ! The cell area integral of the positive values [L2 A ~> m2 a] + real :: areaXnegVals(G%isc:G%iec, G%jsc:G%jec) ! The cell area integral of the negative values [L2 A ~> m2 a] type(EFP_type), dimension(2) :: areaInt_EFP ! An EFP version integral of the values on the current PE [m2 a] real :: scalefac ! A scaling factor for the variable [a A-1 ~> 1] - real :: I_scalefac ! The Adcroft reciprocal of scalefac [A a-1 ~> 1] real :: areaIntPosVals, areaIntNegVals ! The global area integral of the positive and negative values [m2 a] real :: posScale, negScale ! The scaling factor to apply to positive or negative values [nondim] integer :: i,j @@ -667,21 +767,19 @@ subroutine adjust_area_mean_to_zero(array, G, scaling, unit_scale, unscale) if (present(unscale)) then ; scalefac = unscale elseif (present(unit_scale)) then ; scalefac = unit_scale ; endif - I_scalefac = 0.0 ; if (scalefac /= 0.0) I_scalefac = 1.0 / scalefac - ! areaXposVals(:,:) = 0. ! This zeros out halo points. ! areaXnegVals(:,:) = 0. ! This zeros out halo points. do j=G%jsc,G%jec ; do i=G%isc,G%iec - posVals(i,j) = max(0., scalefac*array(i,j)) - areaXposVals(i,j) = G%US%L_to_m**2*G%areaT(i,j) * posVals(i,j) - negVals(i,j) = min(0., scalefac*array(i,j)) - areaXnegVals(i,j) = G%US%L_to_m**2*G%areaT(i,j) * negVals(i,j) + posVals(i,j) = max(0., array(i,j)) + areaXposVals(i,j) = G%areaT(i,j) * posVals(i,j) + negVals(i,j) = min(0., array(i,j)) + areaXnegVals(i,j) = G%areaT(i,j) * negVals(i,j) enddo ; enddo ! Combining the sums like this avoids separate blocking global sums. - areaInt_EFP(1) = reproducing_sum_EFP( areaXposVals, only_on_PE=.true. ) - areaInt_EFP(2) = reproducing_sum_EFP( areaXnegVals, only_on_PE=.true. ) + areaInt_EFP(1) = reproducing_sum_EFP( areaXposVals, only_on_PE=.true., unscale=scalefac*G%US%L_to_m**2 ) + areaInt_EFP(2) = reproducing_sum_EFP( areaXnegVals, only_on_PE=.true., unscale=scalefac*G%US%L_to_m**2 ) call EFP_sum_across_PEs(areaInt_EFP, 2) areaIntPosVals = EFP_to_real( areaInt_EFP(1) ) areaIntNegVals = EFP_to_real( areaInt_EFP(2) ) @@ -691,12 +789,12 @@ subroutine adjust_area_mean_to_zero(array, G, scaling, unit_scale, unscale) if (areaIntPosVals>-areaIntNegVals) then ! Scale down positive values posScale = - areaIntNegVals / areaIntPosVals do j=G%jsc,G%jec ; do i=G%isc,G%iec - array(i,j) = ((posScale * posVals(i,j)) + negVals(i,j)) * I_scalefac + array(i,j) = (posScale * posVals(i,j)) + negVals(i,j) enddo ; enddo elseif (areaIntPosVals<-areaIntNegVals) then ! Scale down negative values negScale = - areaIntPosVals / areaIntNegVals do j=G%jsc,G%jec ; do i=G%isc,G%iec - array(i,j) = (posVals(i,j) + (negScale * negVals(i,j))) * I_scalefac + array(i,j) = posVals(i,j) + (negScale * negVals(i,j)) enddo ; enddo endif endif diff --git a/src/framework/MOM_dyn_horgrid.F90 b/src/framework/MOM_dyn_horgrid.F90 index 3b5aeca214..2e183cdbef 100644 --- a/src/framework/MOM_dyn_horgrid.F90 +++ b/src/framework/MOM_dyn_horgrid.F90 @@ -175,9 +175,9 @@ module MOM_dyn_horgrid df_dx, & !< Derivative d/dx f (Coriolis parameter) at h-points [T-1 L-1 ~> s-1 m-1]. df_dy !< Derivative d/dy f (Coriolis parameter) at h-points [T-1 L-1 ~> s-1 m-1]. - ! These variables are global sums that are useful for 1-d diagnostics and should not be rescaled. - real :: areaT_global !< Global sum of h-cell area [m2] - real :: IareaT_global !< Global sum of inverse h-cell area (1/areaT_global) [m-2] + ! These variables are global sums that are useful for 1-d diagnostics. + real :: areaT_global !< Global sum of h-cell area [L2 ~> m2] + real :: IareaT_global !< Global sum of inverse h-cell area (1/areaT_global) [L-2 ~> m-2] ! These parameters are run-time parameters that are used during some ! initialization routines (but not all) diff --git a/src/ice_shelf/MOM_ice_shelf.F90 b/src/ice_shelf/MOM_ice_shelf.F90 index ac12f18c9d..99b5aeaa36 100644 --- a/src/ice_shelf/MOM_ice_shelf.F90 +++ b/src/ice_shelf/MOM_ice_shelf.F90 @@ -1141,9 +1141,9 @@ subroutine add_shelf_flux(G, US, CS, sfc_state, fluxes, time_step) ! local variables real :: frac_shelf !< The fractional area covered by the ice shelf [nondim]. real :: frac_open !< The fractional area of the ocean that is not covered by the ice shelf [nondim]. - real :: delta_mass_shelf !< Change in ice shelf mass over one time step [R Z m2 T-1 ~> kg s-1] + real :: delta_mass_shelf !< Change in ice shelf mass over one time step [R Z L2 T-1 ~> kg s-1] real :: balancing_flux !< The fresh water flux that balances the integrated melt flux [R Z T-1 ~> kg m-2 s-1] - real :: balancing_area !< total area where the balancing flux is applied [m2] + real :: balancing_area !< total area where the balancing flux is applied [L2 ~> m2] type(time_type) :: dTime !< The time step as a time_type type(time_type) :: Time0 !< The previous time (Time-dt) real, dimension(SZDI_(G),SZDJ_(G)) :: bal_frac !< Fraction of the cell where the mass flux @@ -1315,7 +1315,7 @@ subroutine add_shelf_flux(G, US, CS, sfc_state, fluxes, time_step) endif enddo ; enddo - balancing_area = global_area_integral(bal_frac, G, area=G%areaT) + balancing_area = global_area_integral(bal_frac, G, area=G%areaT, tmp_scale=1.0) if (balancing_area > 0.0) then balancing_flux = ( global_area_integral(ISS%water_flux, G, tmp_scale=US%RZ_T_to_kg_m2s, & area=ISS%area_shelf_h) + & diff --git a/src/initialization/MOM_shared_initialization.F90 b/src/initialization/MOM_shared_initialization.F90 index 1f7a519d9e..95111afb4b 100644 --- a/src/initialization/MOM_shared_initialization.F90 +++ b/src/initialization/MOM_shared_initialization.F90 @@ -1318,7 +1318,7 @@ subroutine compute_global_grid_integrals(G, US) do j=G%jsc,G%jec ; do i=G%isc,G%iec tmpForSumming(i,j) = G%areaT(i,j) * G%mask2dT(i,j) enddo ; enddo - G%areaT_global = US%L_to_m**2 * reproducing_sum(tmpForSumming, unscale=US%L_to_m**2) + G%areaT_global = reproducing_sum(tmpForSumming, unscale=US%L_to_m**2) if (G%areaT_global == 0.0) & call MOM_error(FATAL, "compute_global_grid_integrals: zero ocean area (check topography?)") From 5693232f3867639289c271a01e78f04acfa51744 Mon Sep 17 00:00:00 2001 From: Robert Hallberg Date: Sat, 18 Jan 2025 21:58:27 -0500 Subject: [PATCH 2/2] Diagnose area integrated fluxes in rescaled units Keep 36 area integrated surface mass, heat or salt flux diagnostics in forcing_diagnostics in rescaled units by replacing an unscale argument with a tmp_scale argument to global_area_integral. Also added the corresponding conversion arguments to the register_scalar_field calls for each of these diagnostics, so that the documented units and conversion factors can be used to confirm the correctness of the documented units for these variables. The internal variables used for the integrated or averaged heat, mass or salt fluxes were also separated for clarity about the units of these variables. All answers and diagnostics are bitwise identical. --- src/core/MOM_forcing_type.F90 | 352 ++++++++++++++++++---------------- 1 file changed, 183 insertions(+), 169 deletions(-) diff --git a/src/core/MOM_forcing_type.F90 b/src/core/MOM_forcing_type.F90 index 998713d1f1..494e36e966 100644 --- a/src/core/MOM_forcing_type.F90 +++ b/src/core/MOM_forcing_type.F90 @@ -296,7 +296,7 @@ module MOM_forcing_type end type mech_forcing !> Structure that defines the id handles for the forcing type -type, public :: forcing_diags +type, public :: forcing_diags ; private !>@{ Forcing diagnostic handles ! mass flux diagnostic handles @@ -1485,15 +1485,15 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_taux = register_diag_field('ocean_model', 'taux', diag%axesCu1, Time, & - 'Zonal surface stress from ocean interactions with atmos and ice', & - 'Pa', conversion=US%RLZ_T2_to_Pa, & + 'Zonal surface stress from ocean interactions with atmos and ice', & + 'Pa', conversion=US%RLZ_T2_to_Pa, & standard_name='surface_downward_x_stress', cmor_field_name='tauuo', & cmor_units='N m-2', cmor_long_name='Surface Downward X Stress', & cmor_standard_name='surface_downward_x_stress') handles%id_tauy = register_diag_field('ocean_model', 'tauy', diag%axesCv1, Time, & - 'Meridional surface stress ocean interactions with atmos and ice', & - 'Pa', conversion=US%RLZ_T2_to_Pa, & + 'Meridional surface stress ocean interactions with atmos and ice', & + 'Pa', conversion=US%RLZ_T2_to_Pa, & standard_name='surface_downward_y_stress', cmor_field_name='tauvo', & cmor_units='N m-2', cmor_long_name='Surface Downward Y Stress', & cmor_standard_name='surface_downward_y_stress') @@ -1559,8 +1559,8 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, ! surface mass flux maps handles%id_prcme = register_diag_field('ocean_model', 'PRCmE', diag%axesT1, Time, & - 'Net surface water flux (precip+melt+lrunoff+ice calving-evap)', & - 'kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & + 'Net surface water flux (precip+melt+lrunoff+ice calving-evap)', & + 'kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & standard_name='water_flux_into_sea_water', cmor_field_name='wfo', & cmor_standard_name='water_flux_into_sea_water',cmor_long_name='Water Flux Into Sea Water') @@ -1574,7 +1574,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, ! smg: seaice_melt field requires updates to the sea ice model handles%id_seaice_melt = register_diag_field('ocean_model', 'seaice_melt', & diag%axesT1, Time, 'water flux to ocean from snow/sea ice melting(> 0) or formation(< 0)', & - 'kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & + 'kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics', & cmor_field_name='fsitherm', & cmor_standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics',& @@ -1584,33 +1584,33 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, 'Liquid + frozen precipitation into ocean', 'kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s) handles%id_fprec = register_diag_field('ocean_model', 'fprec', diag%axesT1, Time, & - 'Frozen precipitation into ocean', & - units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & + 'Frozen precipitation into ocean', & + units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & standard_name='snowfall_flux', cmor_field_name='prsn', & cmor_standard_name='snowfall_flux', cmor_long_name='Snowfall Flux where Ice Free Ocean over Sea') handles%id_lprec = register_diag_field('ocean_model', 'lprec', diag%axesT1, Time, & - 'Liquid precipitation into ocean', & - units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & + 'Liquid precipitation into ocean', & + units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & standard_name='rainfall_flux', & cmor_field_name='prlq', cmor_standard_name='rainfall_flux', & cmor_long_name='Rainfall Flux where Ice Free Ocean over Sea') handles%id_vprec = register_diag_field('ocean_model', 'vprec', diag%axesT1, Time, & - 'Virtual liquid precip into ocean due to SSS restoring', & + 'Virtual liquid precip into ocean due to SSS restoring', & units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s) handles%id_frunoff = register_diag_field('ocean_model', 'frunoff', diag%axesT1, Time, & - 'Frozen runoff (calving) and iceberg melt into ocean', & - units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & + 'Frozen runoff (calving) and iceberg melt into ocean', & + units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & standard_name='water_flux_into_sea_water_from_icebergs', & cmor_field_name='ficeberg', & cmor_standard_name='water_flux_into_sea_water_from_icebergs', & cmor_long_name='Water Flux into Seawater from Icebergs') handles%id_lrunoff = register_diag_field('ocean_model', 'lrunoff', diag%axesT1, Time, & - 'Liquid runoff (rivers) into ocean', & - units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & + 'Liquid runoff (rivers) into ocean', & + units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & standard_name='water_flux_into_sea_water_from_rivers', cmor_field_name='friver', & cmor_standard_name='water_flux_into_sea_water_from_rivers', & cmor_long_name='Water Flux into Sea Water From Rivers') @@ -1635,64 +1635,75 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, ! area integrated surface mass transport, all are rescaled to MKS units before area integration. handles%id_total_prcme = register_scalar_field('ocean_model', 'total_PRCmE', Time, diag, & - long_name='Area integrated net surface water flux (precip+melt+liq runoff+ice calving-evap)',& - units='kg s-1', standard_name='water_flux_into_sea_water_area_integrated', & + long_name='Area integrated net surface water flux (precip+melt+liq runoff+ice calving-evap)', & + units='kg s-1', conversion=US%RZL2_to_kg*US%s_to_T, & + standard_name='water_flux_into_sea_water_area_integrated', & cmor_field_name='total_wfo', & cmor_standard_name='water_flux_into_sea_water_area_integrated', & cmor_long_name='Water Transport Into Sea Water Area Integrated') handles%id_total_evap = register_scalar_field('ocean_model', 'total_evap', Time, diag,& long_name='Area integrated evap/condense at ocean surface', & - units='kg s-1', standard_name='water_evaporation_flux_area_integrated', & + units='kg s-1', conversion=US%RZL2_to_kg*US%s_to_T, & + standard_name='water_evaporation_flux_area_integrated', & cmor_field_name='total_evs', & cmor_standard_name='water_evaporation_flux_area_integrated', & cmor_long_name='Evaporation Where Ice Free Ocean over Sea Area Integrated') ! seaice_melt field requires updates to the sea ice model handles%id_total_seaice_melt = register_scalar_field('ocean_model', 'total_icemelt', Time, diag, & - long_name='Area integrated sea ice melt (>0) or form (<0)', units='kg s-1', & + long_name='Area integrated sea ice melt (>0) or form (<0)', & + units='kg s-1', conversion=US%RZL2_to_kg*US%s_to_T, & standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics_area_integrated', & cmor_field_name='total_fsitherm', & cmor_standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics_area_integrated', & cmor_long_name='Water Melt/Form from Sea Ice Area Integrated') handles%id_total_precip = register_scalar_field('ocean_model', 'total_precip', Time, diag, & - long_name='Area integrated liquid+frozen precip into ocean', units='kg s-1') + long_name='Area integrated liquid+frozen precip into ocean', & + units='kg s-1', conversion=US%RZL2_to_kg*US%s_to_T) handles%id_total_fprec = register_scalar_field('ocean_model', 'total_fprec', Time, diag,& - long_name='Area integrated frozen precip into ocean', units='kg s-1', & + long_name='Area integrated frozen precip into ocean', & + units='kg s-1', conversion=US%RZL2_to_kg*US%s_to_T, & standard_name='snowfall_flux_area_integrated', & cmor_field_name='total_prsn', & cmor_standard_name='snowfall_flux_area_integrated', & cmor_long_name='Snowfall Flux where Ice Free Ocean over Sea Area Integrated') handles%id_total_lprec = register_scalar_field('ocean_model', 'total_lprec', Time, diag,& - long_name='Area integrated liquid precip into ocean', units='kg s-1', & + long_name='Area integrated liquid precip into ocean', & + units='kg s-1', conversion=US%RZL2_to_kg*US%s_to_T, & standard_name='rainfall_flux_area_integrated', & cmor_field_name='total_pr', & cmor_standard_name='rainfall_flux_area_integrated', & cmor_long_name='Rainfall Flux where Ice Free Ocean over Sea Area Integrated') handles%id_total_vprec = register_scalar_field('ocean_model', 'total_vprec', Time, diag, & - long_name='Area integrated virtual liquid precip due to SSS restoring', units='kg s-1') + long_name='Area integrated virtual liquid precip due to SSS restoring', & + units='kg s-1', conversion=US%RZL2_to_kg*US%s_to_T) handles%id_total_frunoff = register_scalar_field('ocean_model', 'total_frunoff', Time, diag, & - long_name='Area integrated frozen runoff (calving) & iceberg melt into ocean', units='kg s-1',& + long_name='Area integrated frozen runoff (calving) & iceberg melt into ocean', & + units='kg s-1', conversion=US%RZL2_to_kg*US%s_to_T, & cmor_field_name='total_ficeberg', & cmor_standard_name='water_flux_into_sea_water_from_icebergs_area_integrated', & cmor_long_name='Water Flux into Seawater from Icebergs Area Integrated') handles%id_total_lrunoff = register_scalar_field('ocean_model', 'total_lrunoff', Time, diag,& - long_name='Area integrated liquid runoff into ocean', units='kg s-1', & + long_name='Area integrated liquid runoff into ocean', & + units='kg s-1', conversion=US%RZL2_to_kg*US%s_to_T, & cmor_field_name='total_friver', & cmor_standard_name='water_flux_into_sea_water_from_rivers_area_integrated', & cmor_long_name='Water Flux into Sea Water From Rivers Area Integrated') handles%id_total_net_massout = register_scalar_field('ocean_model', 'total_net_massout', Time, diag, & - long_name='Area integrated mass leaving ocean due to evap and seaice form', units='kg s-1') + long_name='Area integrated mass leaving ocean due to evap and seaice form', & + units='kg s-1', conversion=US%RZL2_to_kg*US%s_to_T) handles%id_total_net_massin = register_scalar_field('ocean_model', 'total_net_massin', Time, diag, & - long_name='Area integrated mass entering ocean due to predip, runoff, ice melt', units='kg s-1') + long_name='Area integrated mass entering ocean due to predip, runoff, ice melt', & + units='kg s-1', conversion=US%RZL2_to_kg*US%s_to_T) !========================================================================= ! area averaged surface mass transport @@ -1719,8 +1730,8 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, cmor_long_name='Rainfall Flux where Ice Free Ocean over Sea Area Averaged') handles%id_fprec_ga = register_scalar_field('ocean_model', 'fprec_ga', Time, diag, & - long_name='Area integrated frozen precip into ocean', & - units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & + long_name='Area integrated frozen precip into ocean', & + units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & standard_name='snowfall_flux_area_averaged', & cmor_field_name='ave_prsn',cmor_standard_name='snowfall_flux_area_averaged', & cmor_long_name='Snowfall Flux where Ice Free Ocean over Sea Area Averaged') @@ -1748,7 +1759,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_hfrunoffds = register_diag_field('ocean_model', 'hfrunoffds', & diag%axesT1, Time, 'Heat content (relative to 0C) of liquid+solid runoff into ocean', & - 'W m-2', conversion=US%QRZ_T_to_W_m2, & + 'W m-2', conversion=US%QRZ_T_to_W_m2, & standard_name='temperature_flux_due_to_runoff_expressed_as_heat_flux_into_sea_water') handles%id_heat_content_lprec = register_diag_field('ocean_model', 'heat_content_lprec', & @@ -1806,7 +1817,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, cmor_long_name='Surface ocean heat flux from SW+LW+latent+sensible+masstransfer+frazil+seaice_melt_heat') handles%id_sw = register_diag_field('ocean_model', 'SW', diag%axesT1, Time, & - 'Shortwave radiation flux into ocean', 'W m-2', conversion=US%QRZ_T_to_W_m2, & + 'Shortwave radiation flux into ocean', 'W m-2', conversion=US%QRZ_T_to_W_m2, & standard_name='net_downward_shortwave_flux_at_sea_water_surface', & cmor_field_name='rsntds', & cmor_standard_name='net_downward_shortwave_flux_at_sea_water_surface', & @@ -1819,7 +1830,8 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, 'W m-2', conversion=US%QRZ_T_to_W_m2) handles%id_LwLatSens = register_diag_field('ocean_model', 'LwLatSens', diag%axesT1, Time, & - 'Combined longwave, latent, and sensible heating at ocean surface', 'W m-2', conversion=US%QRZ_T_to_W_m2) + 'Combined longwave, latent, and sensible heating at ocean surface', & + 'W m-2', conversion=US%QRZ_T_to_W_m2) handles%id_lw = register_diag_field('ocean_model', 'LW', diag%axesT1, Time, & 'Longwave radiation flux into ocean', 'W m-2', conversion=US%QRZ_T_to_W_m2, & @@ -1838,8 +1850,8 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, 'Latent heat flux into ocean due to evaporation/condensation', 'W m-2', conversion=US%QRZ_T_to_W_m2) handles%id_lat_fprec = register_diag_field('ocean_model', 'latent_fprec_diag', diag%axesT1, Time,& - 'Latent heat flux into ocean due to melting of frozen precipitation', 'W m-2', conversion=US%QRZ_T_to_W_m2, & - cmor_field_name='hfsnthermds', & + 'Latent heat flux into ocean due to melting of frozen precipitation', & + 'W m-2', conversion=US%QRZ_T_to_W_m2, cmor_field_name='hfsnthermds', & cmor_standard_name='heat_flux_into_sea_water_due_to_snow_thermodynamics', & cmor_long_name='Latent Heat to Melt Frozen Precipitation') @@ -1873,7 +1885,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_heat_content_frunoff = register_scalar_field('ocean_model', & 'total_heat_content_frunoff', Time, diag, & long_name='Area integrated heat content (relative to 0C) of solid runoff', & - units='W', cmor_field_name='total_hfsolidrunoffds', & + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2, cmor_field_name='total_hfsolidrunoffds', & cmor_standard_name= & 'temperature_flux_due_to_solid_runoff_expressed_as_heat_flux_into_sea_water_area_integrated',& cmor_long_name= & @@ -1882,7 +1894,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_heat_content_lrunoff = register_scalar_field('ocean_model', & 'total_heat_content_lrunoff', Time, diag, & long_name='Area integrated heat content (relative to 0C) of liquid runoff', & - units='W', cmor_field_name='total_hfrunoffds', & + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2, cmor_field_name='total_hfrunoffds', & cmor_standard_name= & 'temperature_flux_due_to_runoff_expressed_as_heat_flux_into_sea_water_area_integrated',& cmor_long_name= & @@ -1891,7 +1903,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_heat_content_lprec = register_scalar_field('ocean_model', & 'total_heat_content_lprec', Time, diag, & long_name='Area integrated heat content (relative to 0C) of liquid precip', & - units='W', cmor_field_name='total_hfrainds', & + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2, cmor_field_name='total_hfrainds', & cmor_standard_name= & 'temperature_flux_due_to_rainfall_expressed_as_heat_flux_into_sea_water_area_integrated',& cmor_long_name= & @@ -1900,32 +1912,32 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_heat_content_fprec = register_scalar_field('ocean_model', & 'total_heat_content_fprec', Time, diag, & long_name='Area integrated heat content (relative to 0C) of frozen precip',& - units='W') + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2) handles%id_total_heat_content_vprec = register_scalar_field('ocean_model', & 'total_heat_content_vprec', Time, diag, & long_name='Area integrated heat content (relative to 0C) of virtual precip',& - units='W') + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2) handles%id_total_heat_content_cond = register_scalar_field('ocean_model', & 'total_heat_content_cond', Time, diag, & long_name='Area integrated heat content (relative to 0C) of condensate',& - units='W') + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2) handles%id_total_heat_content_evap = register_scalar_field('ocean_model', & 'total_heat_content_evap', Time, diag, & long_name='Area integrated heat content (relative to 0C) of evaporation',& - units='W') + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2) handles%id_total_heat_content_surfwater = register_scalar_field('ocean_model', & 'total_heat_content_surfwater', Time, diag, & long_name='Area integrated heat content (relative to 0C) of water crossing surface',& - units='W') + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2) handles%id_total_heat_content_massout = register_scalar_field('ocean_model', & 'total_heat_content_massout', Time, diag, & long_name='Area integrated heat content (relative to 0C) of water leaving ocean', & - units='W', & + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2, & cmor_field_name='total_hfevapds', & cmor_standard_name= & 'temperature_flux_due_to_evaporation_expressed_as_heat_flux_out_of_sea_water_area_integrated',& @@ -1934,17 +1946,17 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_heat_content_massin = register_scalar_field('ocean_model', & 'total_heat_content_massin', Time, diag, & long_name='Area integrated heat content (relative to 0C) of water entering ocean',& - units='W') + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2) handles%id_total_net_heat_coupler = register_scalar_field('ocean_model', & 'total_net_heat_coupler', Time, diag, & long_name='Area integrated surface heat flux from SW+LW+latent+sensible+seaice_melt_heat (via the coupler)',& - units='W') + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2) handles%id_total_net_heat_surface = register_scalar_field('ocean_model', & 'total_net_heat_surface', Time, diag, & long_name='Area integrated surface heat flux from SW+LW+lat+sens+mass+frazil+restore or flux adjustments', & - units='W', & + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2, & cmor_field_name='total_hfds', & cmor_standard_name='surface_downward_heat_flux_in_sea_water_area_integrated', & cmor_long_name= & @@ -1953,7 +1965,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_sw = register_scalar_field('ocean_model', & 'total_sw', Time, diag, & long_name='Area integrated net downward shortwave at sea water surface', & - units='W', & + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2, & cmor_field_name='total_rsntds', & cmor_standard_name='net_downward_shortwave_flux_at_sea_water_surface_area_integrated',& cmor_long_name= & @@ -1962,12 +1974,12 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_LwLatSens = register_scalar_field('ocean_model',& 'total_LwLatSens', Time, diag, & long_name='Area integrated longwave+latent+sensible heating',& - units='W') + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2) handles%id_total_lw = register_scalar_field('ocean_model', & 'total_lw', Time, diag, & long_name='Area integrated net downward longwave at sea water surface', & - units='W', & + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2, & cmor_field_name='total_rlntds', & cmor_standard_name='surface_net_downward_longwave_flux_area_integrated',& cmor_long_name= & @@ -1976,7 +1988,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_lat = register_scalar_field('ocean_model', & 'total_lat', Time, diag, & long_name='Area integrated surface downward latent heat flux', & - units='W', & + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2, & cmor_field_name='total_hflso', & cmor_standard_name='surface_downward_latent_heat_flux_area_integrated',& cmor_long_name= & @@ -1985,12 +1997,12 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_lat_evap = register_scalar_field('ocean_model', & 'total_lat_evap', Time, diag, & long_name='Area integrated latent heat flux due to evap/condense',& - units='W') + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2) handles%id_total_lat_fprec = register_scalar_field('ocean_model', & 'total_lat_fprec', Time, diag, & long_name='Area integrated latent heat flux due to melting frozen precip', & - units='W', & + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2, & cmor_field_name='total_hfsnthermds', & cmor_standard_name='heat_flux_into_sea_water_due_to_snow_thermodynamics_area_integrated',& cmor_long_name= & @@ -1999,7 +2011,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_lat_frunoff = register_scalar_field('ocean_model', & 'total_lat_frunoff', Time, diag, & long_name='Area integrated latent heat flux due to melting icebergs', & - units='W', & + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2, & cmor_field_name='total_hfibthermds', & cmor_standard_name='heat_flux_into_sea_water_due_to_iceberg_thermodynamics_area_integrated',& cmor_long_name= & @@ -2008,7 +2020,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_sens = register_scalar_field('ocean_model', & 'total_sens', Time, diag, & long_name='Area integrated downward sensible heat flux', & - units='W', & + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2, & cmor_field_name='total_hfsso', & cmor_standard_name='surface_downward_sensible_heat_flux_area_integrated',& cmor_long_name= & @@ -2017,12 +2029,12 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_total_heat_added = register_scalar_field('ocean_model',& 'total_heat_adjustment', Time, diag, & long_name='Area integrated surface heat flux from restoring and/or flux adjustment', & - units='W') + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2) handles%id_total_seaice_melt_heat = register_scalar_field('ocean_model',& 'total_seaice_melt_heat', Time, diag, & long_name='Area integrated surface heat flux from snow and sea ice melt', & - units='W') + units='W', conversion=US%QRZ_T_to_W_m2*US%L_to_m**2) !=============================================================== ! area averaged surface heat fluxes @@ -2033,7 +2045,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, units='W m-2', conversion=US%QRZ_T_to_W_m2) handles%id_net_heat_surface_ga = register_scalar_field('ocean_model', & - 'net_heat_surface_ga', Time, diag, long_name= & + 'net_heat_surface_ga', Time, diag, long_name= & 'Area averaged surface heat flux from SW+LW+lat+sens+mass+frazil+restore+seaice_melt_heat or flux adjustments', & units='W m-2', conversion=US%QRZ_T_to_W_m2, & cmor_field_name='ave_hfds', & @@ -2088,7 +2100,7 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, handles%id_saltflux = register_diag_field('ocean_model', 'salt_flux', diag%axesT1, Time,& 'Net salt flux into ocean at surface (restoring + sea-ice)', & - units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & + units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & cmor_field_name='sfdsi', cmor_standard_name='downward_sea_ice_basal_salt_flux', & cmor_long_name='Downward Sea Ice Basal Salt Flux') @@ -2137,18 +2149,20 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, !=============================================================== ! area integrals of surface salt fluxes - handles%id_total_saltflux = register_scalar_field('ocean_model', & - 'total_salt_flux', Time, diag, & - long_name='Area integrated surface salt flux', units='kg s-1', & + handles%id_total_saltflux = register_scalar_field('ocean_model', 'total_salt_flux', & + Time, diag, long_name='Area integrated surface salt flux', & + units='kg s-1', conversion=1e-3*US%RZL2_to_kg*US%s_to_T, & cmor_field_name='total_sfdsi', & cmor_standard_name='downward_sea_ice_basal_salt_flux_area_integrated',& cmor_long_name='Downward Sea Ice Basal Salt Flux Area Integrated') handles%id_total_saltFluxIn = register_scalar_field('ocean_model', 'total_salt_Flux_In', & - Time, diag, long_name='Area integrated surface salt flux at surface from coupler', units='kg s-1') + Time, diag, long_name='Area integrated surface salt flux at surface from coupler', & + units='kg s-1', conversion=1e-3*US%RZL2_to_kg*US%s_to_T) handles%id_total_saltFluxAdded = register_scalar_field('ocean_model', 'total_salt_Flux_Added', & - Time, diag, long_name='Area integrated surface salt flux due to restoring or flux adjustment', units='kg s-1') + Time, diag, long_name='Area integrated surface salt flux due to restoring or flux adjustment', & + units='kg s-1', conversion=1e-3*US%RZL2_to_kg*US%s_to_T) !=============================================================== ! wave forcing diagnostics @@ -2607,11 +2621,13 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h type(ocean_grid_type), pointer :: G ! Grid metric on model index map type(forcing), pointer :: fluxes ! Fluxes on the model index map real, dimension(SZI_(diag%G),SZJ_(diag%G)) :: res ! A temporary array for combinations - ! of fluxes [R Z T-1 ~> kg m-2 s-1] or [Q R Z T-1 ~> W m-2] - real :: total_transport ! for diagnosing integrated boundary transport, in MKS units of [kg s-1] or [W] - real :: ave_flux ! for diagnosing averaged boundary flux in [R Z T-1 ~> kg m-2 s-1] or [Q R Z T-1 ~> W m-2] + ! of mass fluxes [R Z T-1 ~> kg m-2 s-1] or heat fluxes [Q R Z T-1 ~> W m-2] + real :: total_mass_flux ! Diagnostic of an integrated boundary mass flux in [R Z L2 T-1 ~> kg s-1] + real :: total_heat_flux ! Diagnostic of an integrated boundary heat flux in [Q R Z L2 T-1 ~> W] + real :: total_salt_flux ! Diagnostic of an integrated boundary salt flux in [R Z L2 T-1 ~> kg s-1] + real :: ave_mass_flux ! Diagnostic of the average of a surface mass flux in [R Z T-1 ~> kg m-2 s-1] + real :: ave_heat_flux ! Diagnostic of the average of a surface heat flux in [Q R Z T-1 ~> W m-2] real :: I_dt ! inverse time step [T-1 ~> s-1] - real :: ppt2mks ! conversion between ppt and mks units [nondim] integer :: turns ! Number of index quarter turns logical :: mom_enthalpy ! If true (default) enthalpy terms are computed in MOM6 integer :: i, j, is, ie, js, je @@ -2635,7 +2651,6 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h endif I_dt = 1.0 / fluxes%dt_buoy_accum - ppt2mks = 1e-3 is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec call enable_averages(fluxes%dt_buoy_accum, time_end, diag) @@ -2657,12 +2672,12 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h enddo ; enddo if (handles%id_prcme > 0) call post_data(handles%id_prcme, res, diag) if (handles%id_total_prcme > 0) then - total_transport = global_area_integral(res, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_prcme, total_transport, diag) + total_mass_flux = global_area_integral(res, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_prcme, total_mass_flux, diag) endif if (handles%id_prcme_ga > 0) then - ave_flux = global_area_mean(res, G, tmp_scale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_prcme_ga, ave_flux, diag) + ave_mass_flux = global_area_mean(res, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_prcme_ga, ave_mass_flux, diag) endif endif @@ -2684,8 +2699,8 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h enddo ; enddo if (handles%id_net_massout > 0) call post_data(handles%id_net_massout, res, diag) if (handles%id_total_net_massout > 0) then - total_transport = global_area_integral(res, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_net_massout, total_transport, diag) + total_mass_flux = global_area_integral(res, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_net_massout, total_mass_flux, diag) endif endif @@ -2695,7 +2710,6 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h if (handles%id_net_massin > 0 .or. handles%id_total_net_massin > 0) then do j=js,je ; do i=is,ie res(i,j) = 0.0 - if (associated(fluxes%fprec)) res(i,j) = res(i,j) + fluxes%fprec(i,j) if (associated(fluxes%lrunoff)) res(i,j) = res(i,j) + fluxes%lrunoff(i,j) if (associated(fluxes%frunoff)) res(i,j) = res(i,j) + fluxes%frunoff(i,j) @@ -2716,8 +2730,8 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h enddo ; enddo if (handles%id_net_massin > 0) call post_data(handles%id_net_massin, res, diag) if (handles%id_total_net_massin > 0) then - total_transport = global_area_integral(res, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_net_massin, total_transport, diag) + total_mass_flux = global_area_integral(res, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_net_massin, total_mass_flux, diag) endif endif @@ -2727,12 +2741,12 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h if ((handles%id_evap > 0) .and. associated(fluxes%evap)) & call post_data(handles%id_evap, fluxes%evap, diag) if ((handles%id_total_evap > 0) .and. associated(fluxes%evap)) then - total_transport = global_area_integral(fluxes%evap, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_evap, total_transport, diag) + total_mass_flux = global_area_integral(fluxes%evap, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_evap, total_mass_flux, diag) endif if ((handles%id_evap_ga > 0) .and. associated(fluxes%evap)) then - ave_flux = global_area_mean(fluxes%evap, G, tmp_scale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_evap_ga, ave_flux, diag) + ave_mass_flux = global_area_mean(fluxes%evap, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_evap_ga, ave_mass_flux, diag) endif if (associated(fluxes%lprec) .and. associated(fluxes%fprec)) then @@ -2741,72 +2755,72 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h enddo ; enddo if (handles%id_precip > 0) call post_data(handles%id_precip, res, diag) if (handles%id_total_precip > 0) then - total_transport = global_area_integral(res, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_precip, total_transport, diag) + total_mass_flux = global_area_integral(res, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_precip, total_mass_flux, diag) endif if (handles%id_precip_ga > 0) then - ave_flux = global_area_mean(res, G, tmp_scale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_precip_ga, ave_flux, diag) + ave_mass_flux = global_area_mean(res, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_precip_ga, ave_mass_flux, diag) endif endif if (associated(fluxes%lprec)) then if (handles%id_lprec > 0) call post_data(handles%id_lprec, fluxes%lprec, diag) if (handles%id_total_lprec > 0) then - total_transport = global_area_integral(fluxes%lprec, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_lprec, total_transport, diag) + total_mass_flux = global_area_integral(fluxes%lprec, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_lprec, total_mass_flux, diag) endif if (handles%id_lprec_ga > 0) then - ave_flux = global_area_mean(fluxes%lprec, G, tmp_scale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_lprec_ga, ave_flux, diag) + ave_mass_flux = global_area_mean(fluxes%lprec, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_lprec_ga, ave_mass_flux, diag) endif endif if (associated(fluxes%fprec)) then if (handles%id_fprec > 0) call post_data(handles%id_fprec, fluxes%fprec, diag) if (handles%id_total_fprec > 0) then - total_transport = global_area_integral(fluxes%fprec, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_fprec, total_transport, diag) + total_mass_flux = global_area_integral(fluxes%fprec, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_fprec, total_mass_flux, diag) endif if (handles%id_fprec_ga > 0) then - ave_flux = global_area_mean(fluxes%fprec, G, tmp_scale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_fprec_ga, ave_flux, diag) + ave_mass_flux = global_area_mean(fluxes%fprec, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_fprec_ga, ave_mass_flux, diag) endif endif if (associated(fluxes%vprec)) then if (handles%id_vprec > 0) call post_data(handles%id_vprec, fluxes%vprec, diag) if (handles%id_total_vprec > 0) then - total_transport = global_area_integral(fluxes%vprec, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_vprec, total_transport, diag) + total_mass_flux = global_area_integral(fluxes%vprec, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_vprec, total_mass_flux, diag) endif if (handles%id_vprec_ga > 0) then - ave_flux = global_area_mean(fluxes%vprec, G, tmp_scale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_vprec_ga, ave_flux, diag) + ave_mass_flux = global_area_mean(fluxes%vprec, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_vprec_ga, ave_mass_flux, diag) endif endif if (associated(fluxes%lrunoff)) then if (handles%id_lrunoff > 0) call post_data(handles%id_lrunoff, fluxes%lrunoff, diag) if (handles%id_total_lrunoff > 0) then - total_transport = global_area_integral(fluxes%lrunoff, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_lrunoff, total_transport, diag) + total_mass_flux = global_area_integral(fluxes%lrunoff, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_lrunoff, total_mass_flux, diag) endif endif if (associated(fluxes%frunoff)) then if (handles%id_frunoff > 0) call post_data(handles%id_frunoff, fluxes%frunoff, diag) if (handles%id_total_frunoff > 0) then - total_transport = global_area_integral(fluxes%frunoff, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_frunoff, total_transport, diag) + total_mass_flux = global_area_integral(fluxes%frunoff, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_frunoff, total_mass_flux, diag) endif endif if (associated(fluxes%seaice_melt)) then if (handles%id_seaice_melt > 0) call post_data(handles%id_seaice_melt, fluxes%seaice_melt, diag) if (handles%id_total_seaice_melt > 0) then - total_transport = global_area_integral(fluxes%seaice_melt, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_seaice_melt, total_transport, diag) + total_mass_flux = global_area_integral(fluxes%seaice_melt, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_seaice_melt, total_mass_flux, diag) endif endif @@ -2815,64 +2829,64 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h if ((handles%id_heat_content_lrunoff > 0) .and. associated(fluxes%heat_content_lrunoff)) & call post_data(handles%id_heat_content_lrunoff, fluxes%heat_content_lrunoff, diag) if ((handles%id_total_heat_content_lrunoff > 0) .and. associated(fluxes%heat_content_lrunoff)) then - total_transport = global_area_integral(fluxes%heat_content_lrunoff, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_heat_content_lrunoff, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%heat_content_lrunoff, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_heat_content_lrunoff, total_heat_flux, diag) endif if ((handles%id_heat_content_frunoff > 0) .and. associated(fluxes%heat_content_frunoff)) & call post_data(handles%id_heat_content_frunoff, fluxes%heat_content_frunoff, diag) if ((handles%id_total_heat_content_frunoff > 0) .and. associated(fluxes%heat_content_frunoff)) then - total_transport = global_area_integral(fluxes%heat_content_frunoff, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_heat_content_frunoff, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%heat_content_frunoff, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_heat_content_frunoff, total_heat_flux, diag) endif if ((handles%id_heat_content_lprec > 0) .and. associated(fluxes%heat_content_lprec)) & call post_data(handles%id_heat_content_lprec, fluxes%heat_content_lprec, diag) if ((handles%id_total_heat_content_lprec > 0) .and. associated(fluxes%heat_content_lprec)) then - total_transport = global_area_integral(fluxes%heat_content_lprec, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_heat_content_lprec, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%heat_content_lprec, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_heat_content_lprec, total_heat_flux, diag) endif if ((handles%id_heat_content_fprec > 0) .and. associated(fluxes%heat_content_fprec)) & call post_data(handles%id_heat_content_fprec, fluxes%heat_content_fprec, diag) if ((handles%id_total_heat_content_fprec > 0) .and. associated(fluxes%heat_content_fprec)) then - total_transport = global_area_integral(fluxes%heat_content_fprec, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_heat_content_fprec, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%heat_content_fprec, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_heat_content_fprec, total_heat_flux, diag) endif if ((handles%id_heat_content_vprec > 0) .and. associated(fluxes%heat_content_vprec)) & call post_data(handles%id_heat_content_vprec, fluxes%heat_content_vprec, diag) if ((handles%id_total_heat_content_vprec > 0) .and. associated(fluxes%heat_content_vprec)) then - total_transport = global_area_integral(fluxes%heat_content_vprec, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_heat_content_vprec, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%heat_content_vprec, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_heat_content_vprec, total_heat_flux, diag) endif if ((handles%id_heat_content_cond > 0) .and. associated(fluxes%heat_content_cond)) & call post_data(handles%id_heat_content_cond, fluxes%heat_content_cond, diag) if ((handles%id_total_heat_content_cond > 0) .and. associated(fluxes%heat_content_cond)) then - total_transport = global_area_integral(fluxes%heat_content_cond, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_heat_content_cond, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%heat_content_cond, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_heat_content_cond, total_heat_flux, diag) endif if ((handles%id_heat_content_evap > 0) .and. associated(fluxes%heat_content_evap)) & call post_data(handles%id_heat_content_evap, fluxes%heat_content_evap, diag) if ((handles%id_total_heat_content_evap > 0) .and. associated(fluxes%heat_content_evap)) then - total_transport = global_area_integral(fluxes%heat_content_evap, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_heat_content_evap, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%heat_content_evap, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_heat_content_evap, total_heat_flux, diag) endif if ((handles%id_heat_content_massout > 0) .and. associated(fluxes%heat_content_massout)) & call post_data(handles%id_heat_content_massout, fluxes%heat_content_massout, diag) if ((handles%id_total_heat_content_massout > 0) .and. associated(fluxes%heat_content_massout)) then - total_transport = global_area_integral(fluxes%heat_content_massout, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_heat_content_massout, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%heat_content_massout, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_heat_content_massout, total_heat_flux, diag) endif if ((handles%id_heat_content_massin > 0) .and. associated(fluxes%heat_content_massin)) & call post_data(handles%id_heat_content_massin, fluxes%heat_content_massin, diag) if ((handles%id_total_heat_content_massin > 0) .and. associated(fluxes%heat_content_massin)) then - total_transport = global_area_integral(fluxes%heat_content_massin, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_heat_content_massin, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%heat_content_massin, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_heat_content_massin, total_heat_flux, diag) endif if (handles%id_net_heat_coupler > 0 .or. handles%id_total_net_heat_coupler > 0 .or. & @@ -2887,12 +2901,12 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h enddo ; enddo if (handles%id_net_heat_coupler > 0) call post_data(handles%id_net_heat_coupler, res, diag) if (handles%id_total_net_heat_coupler > 0) then - total_transport = global_area_integral(res, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_net_heat_coupler, total_transport, diag) + total_heat_flux = global_area_integral(res, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_net_heat_coupler, total_heat_flux, diag) endif if (handles%id_net_heat_coupler_ga > 0) then - ave_flux = global_area_mean(res, G, tmp_scale=US%QRZ_T_to_W_m2) - call post_data(handles%id_net_heat_coupler_ga, ave_flux, diag) + ave_heat_flux = global_area_mean(res, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_net_heat_coupler_ga, ave_heat_flux, diag) endif endif @@ -2930,12 +2944,12 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h if (handles%id_net_heat_surface > 0) call post_data(handles%id_net_heat_surface, res, diag) if (handles%id_total_net_heat_surface > 0) then - total_transport = global_area_integral(res, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_net_heat_surface, total_transport, diag) + total_heat_flux = global_area_integral(res, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_net_heat_surface, total_heat_flux, diag) endif if (handles%id_net_heat_surface_ga > 0) then - ave_flux = global_area_mean(res, G, tmp_scale=US%QRZ_T_to_W_m2) - call post_data(handles%id_net_heat_surface_ga, ave_flux, diag) + ave_heat_flux = global_area_mean(res, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_net_heat_surface_ga, ave_heat_flux, diag) endif endif @@ -2956,8 +2970,8 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h enddo ; enddo if (handles%id_heat_content_surfwater > 0) call post_data(handles%id_heat_content_surfwater, res, diag) if (handles%id_total_heat_content_surfwater > 0) then - total_transport = global_area_integral(res, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_heat_content_surfwater, total_transport, diag) + total_heat_flux = global_area_integral(res, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_heat_content_surfwater, total_heat_flux, diag) endif endif @@ -2995,8 +3009,8 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h do j=js,je ; do i=is,ie res(i,j) = (fluxes%lw(i,j) + fluxes%latent(i,j)) + fluxes%sens(i,j) enddo ; enddo - total_transport = global_area_integral(res, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_LwLatSens, total_transport, diag) + total_heat_flux = global_area_integral(res, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_LwLatSens, total_heat_flux, diag) endif if ((handles%id_LwLatSens_ga > 0) .and. associated(fluxes%lw) .and. & @@ -3004,8 +3018,8 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h do j=js,je ; do i=is,ie res(i,j) = ((fluxes%lw(i,j) + fluxes%latent(i,j)) + fluxes%sens(i,j)) enddo ; enddo - ave_flux = global_area_mean(res, G, tmp_scale=US%QRZ_T_to_W_m2) - call post_data(handles%id_LwLatSens_ga, ave_flux, diag) + ave_heat_flux = global_area_mean(res, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_LwLatSens_ga, ave_heat_flux, diag) endif if ((handles%id_sw > 0) .and. associated(fluxes%sw)) then @@ -3020,60 +3034,60 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h call post_data(handles%id_sw_nir, fluxes%sw_nir_dir+fluxes%sw_nir_dif, diag) endif if ((handles%id_total_sw > 0) .and. associated(fluxes%sw)) then - total_transport = global_area_integral(fluxes%sw, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_sw, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%sw, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_sw, total_heat_flux, diag) endif if ((handles%id_sw_ga > 0) .and. associated(fluxes%sw)) then - ave_flux = global_area_mean(fluxes%sw, G, tmp_scale=US%QRZ_T_to_W_m2) - call post_data(handles%id_sw_ga, ave_flux, diag) + ave_heat_flux = global_area_mean(fluxes%sw, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_sw_ga, ave_heat_flux, diag) endif if ((handles%id_lw > 0) .and. associated(fluxes%lw)) then call post_data(handles%id_lw, fluxes%lw, diag) endif if ((handles%id_total_lw > 0) .and. associated(fluxes%lw)) then - total_transport = global_area_integral(fluxes%lw, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_lw, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%lw, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_lw, total_heat_flux, diag) endif if ((handles%id_lw_ga > 0) .and. associated(fluxes%lw)) then - ave_flux = global_area_mean(fluxes%lw, G, tmp_scale=US%QRZ_T_to_W_m2) - call post_data(handles%id_lw_ga, ave_flux, diag) + ave_heat_flux = global_area_mean(fluxes%lw, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_lw_ga, ave_heat_flux, diag) endif if ((handles%id_lat > 0) .and. associated(fluxes%latent)) then call post_data(handles%id_lat, fluxes%latent, diag) endif if ((handles%id_total_lat > 0) .and. associated(fluxes%latent)) then - total_transport = global_area_integral(fluxes%latent, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_lat, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%latent, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_lat, total_heat_flux, diag) endif if ((handles%id_lat_ga > 0) .and. associated(fluxes%latent)) then - ave_flux = global_area_mean(fluxes%latent, G, tmp_scale=US%QRZ_T_to_W_m2) - call post_data(handles%id_lat_ga, ave_flux, diag) + ave_heat_flux = global_area_mean(fluxes%latent, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_lat_ga, ave_heat_flux, diag) endif if ((handles%id_lat_evap > 0) .and. associated(fluxes%latent_evap_diag)) then call post_data(handles%id_lat_evap, fluxes%latent_evap_diag, diag) endif if ((handles%id_total_lat_evap > 0) .and. associated(fluxes%latent_evap_diag)) then - total_transport = global_area_integral(fluxes%latent_evap_diag, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_lat_evap, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%latent_evap_diag, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_lat_evap, total_heat_flux, diag) endif if ((handles%id_lat_fprec > 0) .and. associated(fluxes%latent_fprec_diag)) then call post_data(handles%id_lat_fprec, fluxes%latent_fprec_diag, diag) endif if ((handles%id_total_lat_fprec > 0) .and. associated(fluxes%latent_fprec_diag)) then - total_transport = global_area_integral(fluxes%latent_fprec_diag, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_lat_fprec, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%latent_fprec_diag, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_lat_fprec, total_heat_flux, diag) endif if ((handles%id_lat_frunoff > 0) .and. associated(fluxes%latent_frunoff_diag)) then call post_data(handles%id_lat_frunoff, fluxes%latent_frunoff_diag, diag) endif if (handles%id_total_lat_frunoff > 0 .and. associated(fluxes%latent_frunoff_diag)) then - total_transport = global_area_integral(fluxes%latent_frunoff_diag, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_lat_frunoff, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%latent_frunoff_diag, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_lat_frunoff, total_heat_flux, diag) endif if ((handles%id_sens > 0) .and. associated(fluxes%sens)) then @@ -3085,17 +3099,17 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h endif if ((handles%id_total_seaice_melt_heat > 0) .and. associated(fluxes%seaice_melt_heat)) then - total_transport = global_area_integral(fluxes%seaice_melt_heat, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_seaice_melt_heat, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%seaice_melt_heat, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_seaice_melt_heat, total_heat_flux, diag) endif if ((handles%id_total_sens > 0) .and. associated(fluxes%sens)) then - total_transport = global_area_integral(fluxes%sens, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_sens, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%sens, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_sens, total_heat_flux, diag) endif if ((handles%id_sens_ga > 0) .and. associated(fluxes%sens)) then - ave_flux = global_area_mean(fluxes%sens, G, tmp_scale=US%QRZ_T_to_W_m2) - call post_data(handles%id_sens_ga, ave_flux, diag) + ave_heat_flux = global_area_mean(fluxes%sens, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_sens_ga, ave_heat_flux, diag) endif if ((handles%id_heat_added > 0) .and. associated(fluxes%heat_added)) then @@ -3103,8 +3117,8 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h endif if ((handles%id_total_heat_added > 0) .and. associated(fluxes%heat_added)) then - total_transport = global_area_integral(fluxes%heat_added, G, unscale=US%QRZ_T_to_W_m2) - call post_data(handles%id_total_heat_added, total_transport, diag) + total_heat_flux = global_area_integral(fluxes%heat_added, G, tmp_scale=US%QRZ_T_to_W_m2) + call post_data(handles%id_total_heat_added, total_heat_flux, diag) endif @@ -3113,22 +3127,22 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h if ((handles%id_saltflux > 0) .and. associated(fluxes%salt_flux)) & call post_data(handles%id_saltflux, fluxes%salt_flux, diag) if ((handles%id_total_saltflux > 0) .and. associated(fluxes%salt_flux)) then - total_transport = ppt2mks*global_area_integral(fluxes%salt_flux, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_saltflux, total_transport, diag) + total_salt_flux = global_area_integral(fluxes%salt_flux, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_saltflux, total_salt_flux, diag) endif if ((handles%id_saltFluxAdded > 0) .and. associated(fluxes%salt_flux_added)) & call post_data(handles%id_saltFluxAdded, fluxes%salt_flux_added, diag) if ((handles%id_total_saltFluxAdded > 0) .and. associated(fluxes%salt_flux_added)) then - total_transport = ppt2mks*global_area_integral(fluxes%salt_flux_added, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_saltFluxAdded, total_transport, diag) + total_salt_flux = global_area_integral(fluxes%salt_flux_added, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_saltFluxAdded, total_salt_flux, diag) endif if (handles%id_saltFluxIn > 0 .and. associated(fluxes%salt_flux_in)) & call post_data(handles%id_saltFluxIn, fluxes%salt_flux_in, diag) if ((handles%id_total_saltFluxIn > 0) .and. associated(fluxes%salt_flux_in)) then - total_transport = ppt2mks*global_area_integral(fluxes%salt_flux_in, G, unscale=US%RZ_T_to_kg_m2s) - call post_data(handles%id_total_saltFluxIn, total_transport, diag) + total_salt_flux = global_area_integral(fluxes%salt_flux_in, G, tmp_scale=US%RZ_T_to_kg_m2s) + call post_data(handles%id_total_saltFluxIn, total_salt_flux, diag) endif if (handles%id_saltFluxBehind > 0 .and. associated(fluxes%salt_left_behind)) &