diff --git a/src/ALE/MOM_ALE.F90 b/src/ALE/MOM_ALE.F90 index 4ebc395d7a..810f152e4a 100644 --- a/src/ALE/MOM_ALE.F90 +++ b/src/ALE/MOM_ALE.F90 @@ -318,9 +318,9 @@ subroutine ALE_register_diags(Time, G, GV, US, diag, CS) 'Layer Thickness before remapping', get_thickness_units(GV), conversion=GV%H_to_MKS, & v_extensive=.true.) CS%id_T_preale = register_diag_field('ocean_model', 'T_preale', diag%axesTL, Time, & - 'Temperature before remapping', 'degC') + 'Temperature before remapping', 'degC', conversion=US%C_to_degC) CS%id_S_preale = register_diag_field('ocean_model', 'S_preale', diag%axesTL, Time, & - 'Salinity before remapping', 'PSU') + 'Salinity before remapping', 'PSU', conversion=US%S_to_ppt) CS%id_e_preale = register_diag_field('ocean_model', 'e_preale', diag%axesTi, Time, & 'Interface Heights before remapping', 'm', conversion=US%Z_to_m) @@ -451,8 +451,8 @@ subroutine ALE_main( G, GV, US, h, u, v, tv, Reg, CS, OBC, dt, frac_shelf_h) if (CS%debug) then call hchksum(h, "Post-ALE_main h", G%HI, haloshift=0, scale=GV%H_to_m) - call hchksum(tv%T, "Post-ALE_main T", G%HI, haloshift=0) - call hchksum(tv%S, "Post-ALE_main S", G%HI, haloshift=0) + call hchksum(tv%T, "Post-ALE_main T", G%HI, haloshift=0, scale=US%C_to_degC) + call hchksum(tv%S, "Post-ALE_main S", G%HI, haloshift=0, scale=US%S_to_ppt) call uvchksum("Post-ALE_main [uv]", u, v, G%HI, haloshift=0, scale=US%L_T_to_m_s) endif @@ -1160,13 +1160,13 @@ subroutine TS_PLM_edge_values( CS, S_t, S_b, T_t, T_b, G, GV, tv, h, bdry_extrap type(verticalGrid_type), intent(in) :: GV !< Ocean vertical grid structure type(ALE_CS), intent(inout) :: CS !< module control structure real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(inout) :: S_t !< Salinity at the top edge of each layer + intent(inout) :: S_t !< Salinity at the top edge of each layer [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(inout) :: S_b !< Salinity at the bottom edge of each layer + intent(inout) :: S_b !< Salinity at the bottom edge of each layer [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(inout) :: T_t !< Temperature at the top edge of each layer + intent(inout) :: T_t !< Temperature at the top edge of each layer [C ~> degC] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(inout) :: T_b !< Temperature at the bottom edge of each layer + intent(inout) :: T_b !< Temperature at the bottom edge of each layer [C ~> degC] type(thermo_var_ptrs), intent(in) :: tv !< thermodynamics structure real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: h !< layer thickness [H ~> m or kg m-2] diff --git a/src/ALE/MOM_hybgen_regrid.F90 b/src/ALE/MOM_hybgen_regrid.F90 index 22fd474854..cc961b88f2 100644 --- a/src/ALE/MOM_hybgen_regrid.F90 +++ b/src/ALE/MOM_hybgen_regrid.F90 @@ -361,8 +361,8 @@ subroutine hybgen_regrid(G, GV, US, dp, tv, CS, dzInterface, PCM_cell) ! These arrays work with the input column real :: p_col(GV%ke) ! A column of reference pressures [R L2 T-2 ~> Pa] - real :: temp_in(GV%ke) ! A column of input potential temperatures [degC] - real :: saln_in(GV%ke) ! A column of input layer salinities [ppt] + real :: temp_in(GV%ke) ! A column of input potential temperatures [C ~> degC] + real :: saln_in(GV%ke) ! A column of input layer salinities [S ~> ppt] real :: Rcv_in(GV%ke) ! An input column of coordinate potential density [R ~> kg m-3] real :: dp_in(GV%ke) ! The input column of layer thicknesses [H ~> m or kg m-2] logical :: PCM_lay(GV%ke) ! If true for a layer, use PCM remapping for that layer diff --git a/src/ALE/MOM_hybgen_unmix.F90 b/src/ALE/MOM_hybgen_unmix.F90 index a2b94d846b..024a9baffa 100644 --- a/src/ALE/MOM_hybgen_unmix.F90 +++ b/src/ALE/MOM_hybgen_unmix.F90 @@ -139,8 +139,8 @@ subroutine hybgen_unmix(G, GV, US, CS, tv, Reg, ntr, h) real :: dp0cum(GV%ke+1) ! minimum interface depth [H ~> m or kg m-2] real :: Rcv_tgt(GV%ke) ! Target potential density [R ~> kg m-3] - real :: temp(GV%ke) ! A column of potential temperature [degC] - real :: saln(GV%ke) ! A column of salinity [ppt] + real :: temp(GV%ke) ! A column of potential temperature [C ~> degC] + real :: saln(GV%ke) ! A column of salinity [S ~> ppt] real :: Rcv(GV%ke) ! A column of coordinate potential density [R ~> kg m-3] real :: h_col(GV%ke) ! A column of layer thicknesses [H ~> m or kg m-2] real :: p_col(GV%ke) ! A column of reference pressures [R L2 T-2 ~> Pa] @@ -151,8 +151,8 @@ subroutine hybgen_unmix(G, GV, US, CS, tv, Reg, ntr, h) ! vanished layers [H ~> m or kg m-2] real :: dilate ! A factor by which to dilate the target positions from z to z* [nondim] - real :: Th_tot_in, Th_tot_out ! Column integrated temperature [degC H ~> degC m or degC kg m-2] - real :: Sh_tot_in, Sh_tot_out ! Column integrated salinity [ppt H ~> ppt m or ppt kg m-2] + real :: Th_tot_in, Th_tot_out ! Column integrated temperature [C H ~> degC m or degC kg m-2] + real :: Sh_tot_in, Sh_tot_out ! Column integrated salinity [S H ~> ppt m or ppt kg m-2] real :: Trh_tot_in(max(ntr,1)) ! Initial column integrated tracer amounts [conc H ~> conc m or conc kg m-2] real :: Trh_tot_out(max(ntr,1)) ! Final column integrated tracer amounts [conc H ~> conc m or conc kg m-2] @@ -280,8 +280,8 @@ subroutine hybgen_column_unmix(CS, nk, Rcv_tgt, temp, saln, Rcv, eqn_of_state, & integer, intent(in) :: fixlay !< deepest fixed coordinate layer real, intent(in) :: qhrlx(nk+1) !< Relaxation fraction per timestep [nondim], < 1. real, intent(in) :: Rcv_tgt(nk) !< Target potential density [R ~> kg m-3] - real, intent(inout) :: temp(nk) !< A column of potential temperature [degC] - real, intent(inout) :: saln(nk) !< A column of salinity [ppt] + real, intent(inout) :: temp(nk) !< A column of potential temperature [C ~> degC] + real, intent(inout) :: saln(nk) !< A column of salinity [S ~> ppt] real, intent(inout) :: Rcv(nk) !< Coordinate potential density [R ~> kg m-3] type(EOS_type), intent(in) :: eqn_of_state !< Equation of state structure integer, intent(in) :: ntr !< The number of registered passive tracers @@ -299,20 +299,20 @@ subroutine hybgen_column_unmix(CS, nk, Rcv_tgt, temp, saln, Rcv, eqn_of_state, & ! ! Local variables real :: h_hat ! A portion of a layer to move across an interface [H ~> m or kg m-2] - real :: delt, deltm ! Temperature differences between successive layers [degC] - real :: dels, delsm ! Salinity differences between successive layers [ppt] + real :: delt, deltm ! Temperature differences between successive layers [C ~> degC] + real :: dels, delsm ! Salinity differences between successive layers [S ~> ppt] real :: abs_dRdT ! The absolute value of the derivative of the coordinate density - ! with temperature [R degC-1 ~> kg m-3 degC-1] + ! with temperature [R C-1 ~> kg m-3 degC-1] real :: abs_dRdS ! The absolute value of the derivative of the coordinate density - ! with salinity [R ppt-1 ~> kg m-3 ppt-1] + ! with salinity [R S-1 ~> kg m-3 ppt-1] real :: q, qts ! Nondimensional fractions in the range of 0 to 1 [nondim] real :: frac_dts ! The fraction of the temperature or salinity difference between successive ! layers by which the source layer's property changes by the loss of water ! that matches the destination layers properties via unmixing [nondim]. real :: qtr ! The fraction of the water that will come from the layer below, ! used for updating the concentration of passive tracers [nondim] - real :: swap_T ! A swap variable for temperature [degC] - real :: swap_S ! A swap variable for salinity [ppt] + real :: swap_T ! A swap variable for temperature [C ~> degC] + real :: swap_S ! A swap variable for salinity [S ~> ppt] real :: swap_tr ! A temporary swap variable for the tracers [conc] logical, parameter :: lunmix=.true. ! unmix a too light deepest layer integer :: k, ka, kp, kt, m diff --git a/src/ALE/MOM_regridding.F90 b/src/ALE/MOM_regridding.F90 index 95a77f503d..562bc80d67 100644 --- a/src/ALE/MOM_regridding.F90 +++ b/src/ALE/MOM_regridding.F90 @@ -1594,7 +1594,7 @@ subroutine build_grid_adaptive(G, GV, US, h, tv, dzInterface, remapCS, CS) ! local variables integer :: i, j, k, nz ! indices and dimension lengths - ! temperature, salinity and pressure on interfaces + ! temperature [C ~> degC], salinity [S ~> ppt] and pressure on interfaces real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: tInt, sInt ! current interface positions and after tendency term is applied ! positive downward @@ -1936,8 +1936,8 @@ subroutine convective_adjustment(G, GV, h, tv) !------------------------------------------------------------------------------ ! Local variables - real :: T0, T1 ! temperatures of two layers [degC] - real :: S0, S1 ! salinities of two layers [ppt] + real :: T0, T1 ! temperatures of two layers [C ~> degC] + real :: S0, S1 ! salinities of two layers [S ~> ppt] real :: r0, r1 ! densities of two layers [R ~> kg m-3] real :: h0, h1 ! Layer thicknesses [H ~> m or kg m-2] real, dimension(GV%ke) :: p_col ! A column of zero pressures [R L2 T-2 ~> Pa] @@ -1953,7 +1953,7 @@ subroutine convective_adjustment(G, GV, h, tv) do j = G%jsc-1,G%jec+1 ; do i = G%isc-1,G%iec+1 ! Compute densities within current water column - call calculate_density( tv%T(i,j,:), tv%S(i,j,:), p_col, densities, tv%eqn_of_state) + call calculate_density(tv%T(i,j,:), tv%S(i,j,:), p_col, densities, tv%eqn_of_state) ! Repeat restratification until complete do @@ -1972,8 +1972,8 @@ subroutine convective_adjustment(G, GV, h, tv) tv%S(i,j,k) = S1 ; tv%S(i,j,k+1) = S0 h(i,j,k) = h1 ; h(i,j,k+1) = h0 ! Recompute densities at levels k and k+1 - call calculate_density( tv%T(i,j,k), tv%S(i,j,k), p_col(k), densities(k), tv%eqn_of_state) - call calculate_density( tv%T(i,j,k+1), tv%S(i,j,k+1), p_col(k+1), & + call calculate_density(tv%T(i,j,k), tv%S(i,j,k), p_col(k), densities(k), tv%eqn_of_state) + call calculate_density(tv%T(i,j,k+1), tv%S(i,j,k+1), p_col(k+1), & densities(k+1), tv%eqn_of_state ) ! Because p_col is has uniform values, these calculate_density calls are equivalent to ! densities(k) = r1 ; densities(k+1) = r0 diff --git a/src/ALE/coord_adapt.F90 b/src/ALE/coord_adapt.F90 index e5b33103ef..91df78c021 100644 --- a/src/ALE/coord_adapt.F90 +++ b/src/ALE/coord_adapt.F90 @@ -122,8 +122,8 @@ subroutine build_adapt_column(CS, G, GV, US, tv, i, j, zInt, tInt, sInt, h, zNex integer, intent(in) :: i !< The i-index of the column to work on integer, intent(in) :: j !< The j-index of the column to work on real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), intent(in) :: zInt !< Interface heights [H ~> m or kg m-2]. - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), intent(in) :: tInt !< Interface temperatures [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), intent(in) :: sInt !< Interface salinities [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), intent(in) :: tInt !< Interface temperatures [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), intent(in) :: sInt !< Interface salinities [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2] real, dimension(SZK_(GV)+1), intent(inout) :: zNext !< updated interface positions @@ -131,8 +131,8 @@ subroutine build_adapt_column(CS, G, GV, US, tv, i, j, zInt, tInt, sInt, h, zNex integer :: k, nz real :: h_up, b1, b_denom_1, d1, depth, nominal_z, stretching real :: drdz ! The vertical density gradient [R H-1 ~> kg m-4 or m-1] - real, dimension(SZK_(GV)+1) :: alpha ! drho/dT [R degC-1 ~> kg m-3 degC-1] - real, dimension(SZK_(GV)+1) :: beta ! drho/dS [R ppt-1 ~> kg m-3 ppt-1] + real, dimension(SZK_(GV)+1) :: alpha ! drho/dT [R C-1 ~> kg m-3 degC-1] + real, dimension(SZK_(GV)+1) :: beta ! drho/dS [R S-1 ~> kg m-3 ppt-1] real, dimension(SZK_(GV)+1) :: del2sigma ! Laplacian of in situ density times grid spacing [R ~> kg m-3] real, dimension(SZK_(GV)+1) :: dh_d2s ! Thickness change in response to del2sigma [H ~> m or kg m-2] real, dimension(SZK_(GV)) :: kGrid, c1 ! grid diffusivity on layers, and tridiagonal work array diff --git a/src/ALE/coord_hycom.F90 b/src/ALE/coord_hycom.F90 index 4d70f925aa..5a3ffaff52 100644 --- a/src/ALE/coord_hycom.F90 +++ b/src/ALE/coord_hycom.F90 @@ -101,8 +101,8 @@ subroutine build_hycom1_column(CS, eqn_of_state, nz, depth, h, T, S, p_col, & type(EOS_type), intent(in) :: eqn_of_state !< Equation of state structure integer, intent(in) :: nz !< Number of levels real, intent(in) :: depth !< Depth of ocean bottom (positive [H ~> m or kg m-2]) - real, dimension(nz), intent(in) :: T !< Temperature of column [degC] - real, dimension(nz), intent(in) :: S !< Salinity of column [ppt] + real, dimension(nz), intent(in) :: T !< Temperature of column [C ~> degC] + real, dimension(nz), intent(in) :: S !< Salinity of column [S ~> ppt] real, dimension(nz), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2] real, dimension(nz), intent(in) :: p_col !< Layer pressure [R L2 T-2 ~> Pa] real, dimension(nz+1), intent(in) :: z_col !< Interface positions relative to the surface [H ~> m or kg m-2] diff --git a/src/ALE/coord_rho.F90 b/src/ALE/coord_rho.F90 index 4a9872d429..0cbf025b94 100644 --- a/src/ALE/coord_rho.F90 +++ b/src/ALE/coord_rho.F90 @@ -93,8 +93,8 @@ subroutine build_rho_column(CS, nz, depth, h, T, S, eqn_of_state, z_interface, & integer, intent(in) :: nz !< Number of levels on source grid (i.e. length of h, T, S) real, intent(in) :: depth !< Depth of ocean bottom (positive downward) [H ~> m or kg m-2] real, dimension(nz), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2] - real, dimension(nz), intent(in) :: T !< Temperature for source column [degC] - real, dimension(nz), intent(in) :: S !< Salinity for source column [ppt] + real, dimension(nz), intent(in) :: T !< Temperature for source column [C ~> degC] + real, dimension(nz), intent(in) :: S !< Salinity for source column [S ~> ppt] type(EOS_type), intent(in) :: eqn_of_state !< Equation of state structure real, dimension(CS%nk+1), & intent(inout) :: z_interface !< Absolute positions of interfaces @@ -206,8 +206,8 @@ subroutine build_rho_column_iteratively(CS, remapCS, nz, depth, h, T, S, eqn_of_ integer, intent(in) :: nz !< Number of levels real, intent(in) :: depth !< Depth of ocean bottom [Z ~> m] real, dimension(nz), intent(in) :: h !< Layer thicknesses in Z coordinates [Z ~> m] - real, dimension(nz), intent(in) :: T !< T for column [degC] - real, dimension(nz), intent(in) :: S !< S for column [ppt] + real, dimension(nz), intent(in) :: T !< T for column [C ~> degC] + real, dimension(nz), intent(in) :: S !< S for column [S ~> ppt] type(EOS_type), intent(in) :: eqn_of_state !< Equation of state structure real, dimension(nz+1), intent(inout) :: zInterface !< Absolute positions of interfaces real, optional, intent(in) :: h_neglect !< A negligibly small width for the @@ -224,7 +224,7 @@ subroutine build_rho_column_iteratively(CS, remapCS, nz, depth, h, T, S, eqn_of_ real, dimension(nz+1) :: x0, x1, xTmp ! Temporary interface heights [Z ~> m] real, dimension(nz) :: pres ! The pressure used in the equation of state [R L2 T-2 ~> Pa]. real, dimension(nz) :: densities ! Layer densities [R ~> kg m-3] - real, dimension(nz) :: T_tmp, S_tmp ! A temporary profile of temperature [degC] and salinity [ppt]. + real, dimension(nz) :: T_tmp, S_tmp ! A temporary profile of temperature [C ~> degC] and salinity [S ~> ppt]. real, dimension(nz) :: Tmp ! A temporary variable holding a remapped variable. real, dimension(nz) :: h0, h1, hTmp ! Temporary thicknesses [Z ~> m] real :: deviation ! When iterating to determine the final grid, this is the @@ -263,7 +263,7 @@ subroutine build_rho_column_iteratively(CS, remapCS, nz, depth, h, T, S, eqn_of_ enddo ! Compute densities within current water column - call calculate_density( T_tmp, S_tmp, pres, densities, eqn_of_state) + call calculate_density(T_tmp, S_tmp, pres, densities, eqn_of_state) do k = 1,count_nonzero_layers densities(k) = densities(mapping(k)) diff --git a/src/ALE/coord_slight.F90 b/src/ALE/coord_slight.F90 index 6c2432d50d..4b4ac8a153 100644 --- a/src/ALE/coord_slight.F90 +++ b/src/ALE/coord_slight.F90 @@ -187,8 +187,8 @@ subroutine build_slight_column(CS, eqn_of_state, H_to_pres, H_subroundoff, & real, intent(in) :: H_subroundoff !< GV%H_subroundoff integer, intent(in) :: nz !< Number of levels real, intent(in) :: depth !< Depth of ocean bottom (positive [H ~> m or kg m-2]) - real, dimension(nz), intent(in) :: T_col !< T for column - real, dimension(nz), intent(in) :: S_col !< S for column + real, dimension(nz), intent(in) :: T_col !< T for column [C ~> degC] + real, dimension(nz), intent(in) :: S_col !< S for column [S ~> ppt] real, dimension(nz), intent(in) :: h_col !< Layer thicknesses [H ~> m or kg m-2] real, dimension(nz), intent(in) :: p_col !< Layer center pressure [R L2 T-2 ~> Pa] real, dimension(nz+1), intent(in) :: z_col !< Interface positions relative to the surface [H ~> m or kg m-2] @@ -199,20 +199,20 @@ subroutine build_slight_column(CS, eqn_of_state, H_to_pres, H_subroundoff, & !! of edge value calculations [H ~> m or kg m-2]. ! Local variables real, dimension(nz) :: rho_col ! Layer densities [R ~> kg m-3] - real, dimension(nz) :: T_f, S_f ! Filtered layer temperature [degC] and salinity [ppt] + real, dimension(nz) :: T_f, S_f ! Filtered layer temperature [C ~> degC] and salinity [S ~> ppt] logical, dimension(nz+1) :: reliable ! If true, this interface is in a reliable position. - real, dimension(nz+1) :: T_int, S_int ! Temperature [degC] and salinity [ppt] interpolated to interfaces. + real, dimension(nz+1) :: T_int, S_int ! Temperature [C ~> degC] and salinity [S ~> ppt] interpolated to interfaces. real, dimension(nz+1) :: rho_tmp ! A temporary density [R ~> kg m-3] real, dimension(nz+1) :: drho_dp ! The partial derivative of density with pressure [T2 L-2 ~> kg m-3 Pa-1] real, dimension(nz+1) :: p_IS, p_R ! Pressures [R L2 T-2 ~> Pa] real, dimension(nz+1) :: drhoIS_dT ! The partial derivative of in situ density with temperature - ! in [R degC-1 ~> kg m-3 degC-1] + ! in [R C-1 ~> kg m-3 degC-1] real, dimension(nz+1) :: drhoIS_dS ! The partial derivative of in situ density with salinity - ! in [R ppt-1 ~> kg m-3 ppt-1] + ! in [R S-1 ~> kg m-3 ppt-1] real, dimension(nz+1) :: drhoR_dT ! The partial derivative of reference density with temperature - ! in [R degC-1 ~> kg m-3 degC-1] + ! in [R C-1 ~> kg m-3 degC-1] real, dimension(nz+1) :: drhoR_dS ! The partial derivative of reference density with salinity - ! in [R ppt-1 ~> kg m-3 ppt-1] + ! in [R S-1 ~> kg m-3 ppt-1] real, dimension(nz+1) :: strat_rat real :: H_to_cPa ! A conversion factor from thicknesses to the compressibility fraction times ! the units of pressure [R L2 T-2 H-1 ~> Pa m-1 or Pa m2 kg-1] diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index c4f3d40343..82c4692c1e 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -181,8 +181,8 @@ module MOM type, public :: MOM_control_struct ; private real ALLOCABLE_, dimension(NIMEM_,NJMEM_,NKMEM_) :: & h, & !< layer thickness [H ~> m or kg m-2] - T, & !< potential temperature [degC] - S !< salinity [ppt] + T, & !< potential temperature [C ~> degC] + S !< salinity [S ~> ppt] real ALLOCABLE_, dimension(NIMEMB_PTR_,NJMEM_,NKMEM_) :: & u, & !< zonal velocity component [L T-1 ~> m s-1] uh, & !< uh = u * h * dy at u grid points [H L2 T-1 ~> m3 s-1 or kg s-1] @@ -286,10 +286,6 @@ module MOM real, dimension(:,:), pointer :: frac_shelf_h => NULL() !< fraction of total area occupied !! by ice shelf [nondim] real, dimension(:,:), pointer :: mass_shelf => NULL() !< Mass of ice shelf [R Z ~> kg m-2] - real, dimension(:,:,:), pointer :: & - h_pre_dyn => NULL(), & !< The thickness before the transports [H ~> m or kg m-2]. - T_pre_dyn => NULL(), & !< Temperature before the transports [degC]. - S_pre_dyn => NULL() !< Salinity before the transports [ppt]. type(accel_diag_ptrs) :: ADp !< structure containing pointers to accelerations, !! for derived diagnostics (e.g., energy budgets) type(cont_diag_ptrs) :: CDp !< structure containing pointers to continuity equation @@ -1231,12 +1227,12 @@ subroutine step_MOM_tracer_dyn(CS, G, GV, US, h, Time_local) call hchksum(h,"Pre-advection h", G%HI, haloshift=1, scale=GV%H_to_m) call uvchksum("Pre-advection uhtr", CS%uhtr, CS%vhtr, G%HI, & haloshift=0, scale=GV%H_to_m*US%L_to_m**2) - if (associated(CS%tv%T)) call hchksum(CS%tv%T, "Pre-advection T", G%HI, haloshift=1) - if (associated(CS%tv%S)) call hchksum(CS%tv%S, "Pre-advection S", G%HI, haloshift=1) + if (associated(CS%tv%T)) call hchksum(CS%tv%T, "Pre-advection T", G%HI, haloshift=1, scale=US%C_to_degC) + if (associated(CS%tv%S)) call hchksum(CS%tv%S, "Pre-advection S", G%HI, haloshift=1, scale=US%S_to_ppt) if (associated(CS%tv%frazil)) call hchksum(CS%tv%frazil, "Pre-advection frazil", G%HI, haloshift=0, & scale=US%Q_to_J_kg*US%RZ_to_kg_m2) if (associated(CS%tv%salt_deficit)) call hchksum(CS%tv%salt_deficit, & - "Pre-advection salt deficit", G%HI, haloshift=0, scale=US%RZ_to_kg_m2) + "Pre-advection salt deficit", G%HI, haloshift=0, scale=US%S_to_ppt*US%RZ_to_kg_m2) ! call MOM_thermo_chksum("Pre-advection ", CS%tv, G, US) call cpu_clock_end(id_clock_other) endif @@ -1415,8 +1411,8 @@ subroutine step_MOM_thermo(CS, G, GV, US, u, v, h, tv, fluxes, dtdia, & if (CS%debug) then call MOM_state_chksum("Pre-ALE ", u, v, h, CS%uh, CS%vh, G, GV, US) - call hchksum(tv%T,"Pre-ALE T", G%HI, haloshift=1) - call hchksum(tv%S,"Pre-ALE S", G%HI, haloshift=1) + call hchksum(tv%T,"Pre-ALE T", G%HI, haloshift=1, scale=US%C_to_degC) + call hchksum(tv%S,"Pre-ALE S", G%HI, haloshift=1, scale=US%S_to_ppt) call check_redundant("Pre-ALE ", u, v, G) endif call cpu_clock_begin(id_clock_ALE) @@ -1442,8 +1438,8 @@ subroutine step_MOM_thermo(CS, G, GV, US, u, v, h, tv, fluxes, dtdia, & if (CS%debug .and. CS%use_ALE_algorithm) then call MOM_state_chksum("Post-ALE ", u, v, h, CS%uh, CS%vh, G, GV, US) - call hchksum(tv%T, "Post-ALE T", G%HI, haloshift=1) - call hchksum(tv%S, "Post-ALE S", G%HI, haloshift=1) + call hchksum(tv%T, "Post-ALE T", G%HI, haloshift=1, scale=US%C_to_degC) + call hchksum(tv%S, "Post-ALE S", G%HI, haloshift=1, scale=US%S_to_ppt) call check_redundant("Post-ALE ", u, v, G) endif @@ -1462,8 +1458,8 @@ subroutine step_MOM_thermo(CS, G, GV, US, u, v, h, tv, fluxes, dtdia, & haloshift=0, scale=GV%H_to_m*US%L_to_m**2) ! call MOM_state_chksum("Post-diabatic ", u, v, & ! h, CS%uhtr, CS%vhtr, G, GV, haloshift=1) - if (associated(tv%T)) call hchksum(tv%T, "Post-diabatic T", G%HI, haloshift=1) - if (associated(tv%S)) call hchksum(tv%S, "Post-diabatic S", G%HI, haloshift=1) + if (associated(tv%T)) call hchksum(tv%T, "Post-diabatic T", G%HI, haloshift=1, scale=US%C_to_degC) + if (associated(tv%S)) call hchksum(tv%S, "Post-diabatic S", G%HI, haloshift=1, scale=US%S_to_ppt) if (associated(tv%frazil)) call hchksum(tv%frazil, "Post-diabatic frazil", G%HI, haloshift=0, & scale=US%Q_to_J_kg*US%RZ_to_kg_m2) if (associated(tv%salt_deficit)) call hchksum(tv%salt_deficit, & @@ -1486,8 +1482,8 @@ subroutine step_MOM_thermo(CS, G, GV, US, u, v, h, tv, fluxes, dtdia, & call create_group_pass(pass_T_S, tv%S, G%Domain, To_All+Omit_Corners, halo=1) call do_group_pass(pass_T_S, G%Domain, clock=id_clock_pass) if (CS%debug) then - if (associated(tv%T)) call hchksum(tv%T, "Post-diabatic T", G%HI, haloshift=1) - if (associated(tv%S)) call hchksum(tv%S, "Post-diabatic S", G%HI, haloshift=1) + if (associated(tv%T)) call hchksum(tv%T, "Post-diabatic T", G%HI, haloshift=1, scale=US%C_to_degC) + if (associated(tv%S)) call hchksum(tv%S, "Post-diabatic S", G%HI, haloshift=1, scale=US%S_to_ppt) endif endif @@ -1746,8 +1742,8 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, & ! by an ice shelf [nondim] real, allocatable, target :: mass_shelf_in(:,:) ! Initial mass of ice shelf contained within a grid cell ! [R Z ~> kg m-2] - real, allocatable, target :: T_in(:,:,:) ! Initial temperatures [degC] - real, allocatable, target :: S_in(:,:,:) ! Initial salinities [ppt] + real, allocatable, target :: T_in(:,:,:) ! Initial temperatures [C ~> degC] + real, allocatable, target :: S_in(:,:,:) ! Initial salinities [S ~> ppt] type(ocean_OBC_type), pointer :: OBC_in => NULL() type(sponge_CS), pointer :: sponge_in_CSp => NULL() @@ -2025,13 +2021,13 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, & "drive the salinity negative otherwise.)", default=.false.) call get_param(param_file, "MOM", "MIN_SALINITY", CS%tv%min_salinity, & "The minimum value of salinity when BOUND_SALINITY=True.", & - units="PPT", default=0.0, do_not_log=.not.bound_salinity) + units="PPT", default=0.0, scale=US%ppt_to_S, do_not_log=.not.bound_salinity) call get_param(param_file, "MOM", "C_P", CS%tv%C_p, & "The heat capacity of sea water, approximated as a "//& "constant. This is only used if ENABLE_THERMODYNAMICS is "//& "true. The default value is from the TEOS-10 definition "//& "of conservative temperature.", units="J kg-1 K-1", & - default=3991.86795711963, scale=US%J_kg_to_Q) + default=3991.86795711963, scale=US%J_kg_to_Q*US%C_to_degC) call get_param(param_file, "MOM", "USE_PSURF_IN_EOS", CS%use_p_surf_in_EOS, & "If true, always include the surface pressure contributions "//& "in equation of state calculations.", default=.true.) @@ -2309,31 +2305,31 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, & if (CS%tv%S_is_absS) then vd_S = var_desc(name="abssalt", units="g kg-1", longname="Absolute Salinity", & cmor_field_name="so", cmor_longname="Sea Water Salinity", & - conversion=0.001) + conversion=0.001*US%S_to_ppt) else vd_S = var_desc(name="salt", units="psu", longname="Salinity", & cmor_field_name="so", cmor_longname="Sea Water Salinity", & - conversion=0.001) + conversion=0.001*US%S_to_ppt) endif if (advect_TS) then S_flux_units = get_tr_flux_units(GV, "psu") ! Could change to "kg m-2 s-1"? conv2watt = GV%H_to_kg_m2 * US%Q_to_J_kg*CS%tv%C_p if (GV%Boussinesq) then - conv2salt = GV%H_to_m ! Could change to GV%H_to_kg_m2 * 0.001? + conv2salt = US%S_to_ppt*GV%H_to_m ! Could change to US%S_to_ppt*GV%H_to_kg_m2 * 0.001? else - conv2salt = GV%H_to_kg_m2 + conv2salt = US%S_to_ppt*GV%H_to_kg_m2 endif call register_tracer(CS%tv%T, CS%tracer_Reg, param_file, HI, GV, & - tr_desc=vd_T, registry_diags=.true., flux_nameroot='T', & - flux_units='W', flux_longname='Heat', & + tr_desc=vd_T, registry_diags=.true., conc_scale=US%C_to_degC, & + flux_nameroot='T', flux_units='W', flux_longname='Heat', & flux_scale=conv2watt, convergence_units='W m-2', & convergence_scale=conv2watt, CMOR_tendprefix="opottemp", diag_form=2) call register_tracer(CS%tv%S, CS%tracer_Reg, param_file, HI, GV, & - tr_desc=vd_S, registry_diags=.true., flux_nameroot='S', & - flux_units=S_flux_units, flux_longname='Salt', & + tr_desc=vd_S, registry_diags=.true., conc_scale=US%S_to_ppt, & + flux_nameroot='S', flux_units=S_flux_units, flux_longname='Salt', & flux_scale=conv2salt, convergence_units='kg m-2 s-1', & - convergence_scale=0.001*GV%H_to_kg_m2, CMOR_tendprefix="osalt", diag_form=2) + convergence_scale=0.001*US%S_to_ppt*GV%H_to_kg_m2, CMOR_tendprefix="osalt", diag_form=2) endif endif @@ -2443,7 +2439,7 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, & ! ! While incorrect and potentially dangerous, it does not seem that this ! pointer is used during initialization, so we leave it for now. - call register_temp_salt_segments(GV, OBC_in, CS%tracer_Reg, param_file) + call register_temp_salt_segments(GV, US, OBC_in, CS%tracer_Reg, param_file) endif if (associated(CS%OBC)) then @@ -2454,7 +2450,7 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, & ! This is the equivalent to 2 calls to register_segment_tracer (per segment), which ! could occur with the call to update_OBC_data or after the main initialization. if (use_temperature) & - call register_temp_salt_segments(GV, CS%OBC, CS%tracer_Reg, param_file) + call register_temp_salt_segments(GV, US, CS%OBC, CS%tracer_Reg, param_file) ! This needs the number of tracers and to have called any code that sets whether ! reservoirs are used. @@ -2923,7 +2919,7 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, & (LEN_TRIM(dirs%input_filename) == 1)) if (CS%ensemble_ocean) then - call init_oda(Time, G, GV, CS%diag, CS%odaCS) + call init_oda(Time, G, GV, US, CS%diag, CS%odaCS) endif ! initialize stochastic physics @@ -3077,10 +3073,10 @@ subroutine set_restart_fields(GV, US, param_file, CS, restart_CSp) if (associated(CS%tv%T)) & call register_restart_field(CS%tv%T, "Temp", .true., restart_CSp, & - "Potential Temperature", "degC") + "Potential Temperature", "degC", conversion=US%C_to_degC) if (associated(CS%tv%S)) & call register_restart_field(CS%tv%S, "Salt", .true., restart_CSp, & - "Salinity", "PPT") + "Salinity", "PPT", conversion=US%S_to_ppt) call register_restart_field(CS%h, "h", .true., restart_CSp, & "Layer Thickness", thickness_units, conversion=GV%H_to_MKS) @@ -3194,13 +3190,14 @@ subroutine extract_surface_state(CS, sfc_state_in) !! layer properties [Z ~> m] or [H ~> m or kg m-2] real :: dh !< Thickness of a layer within the mixed layer [Z ~> m] or [H ~> m or kg m-2] real :: mass !< Mass per unit area of a layer [R Z ~> kg m-2] - real :: T_freeze !< freezing temperature [degC] real :: I_depth !< The inverse of depth [Z-1 ~> m-1] or [H-1 ~> m-1 or m2 kg-1] real :: missing_depth !< The portion of depth_ml that can not be found in a column [H ~> m or kg m-2] real :: H_rescale !< A conversion factor from thickness units to the units used in the !! calculation of properties of the uppermost ocean [nondim] or [Z H-1 ~> 1 or m3 kg-1] ! After the ANSWERS_2018 flag has been obsoleted, H_rescale will be 1. - real :: delT(SZI_(CS%G)) !< Depth integral of T-T_freeze [Z degC ~> m degC] + real :: T_freeze(SZI_(CS%G)) !< freezing temperature [C ~> degC] + real :: pres(SZI_(CS%G)) !< Pressure to use for the freezing temperature calculation [R L2 T-2 ~> Pa] + real :: delT(SZI_(CS%G)) !< Depth integral of T-T_freeze [Z C ~> m degC] logical :: use_temperature !< If true, temperature and salinity are used as state variables. integer :: i, j, k, is, ie, js, je, nz, numberOfErrors, ig, jg integer :: isd, ied, jsd, jed @@ -3264,8 +3261,8 @@ subroutine extract_surface_state(CS, sfc_state_in) if (CS%Hmix < 0.0) then ! A bulk mixed layer is in use, so layer 1 has the properties if (use_temperature) then ; do j=js,je ; do i=is,ie - sfc_state%SST(i,j) = CS%tv%T(i,j,1) - sfc_state%SSS(i,j) = CS%tv%S(i,j,1) + sfc_state%SST(i,j) = US%C_to_degC*CS%tv%T(i,j,1) + sfc_state%SSS(i,j) = US%S_to_ppt*CS%tv%S(i,j,1) enddo ; enddo ; endif do j=js,je ; do I=is-1,ie sfc_state%u(I,j) = CS%u(I,j,1) @@ -3300,8 +3297,8 @@ subroutine extract_surface_state(CS, sfc_state_in) dh = 0.0 endif if (use_temperature) then - sfc_state%SST(i,j) = sfc_state%SST(i,j) + dh * CS%tv%T(i,j,k) - sfc_state%SSS(i,j) = sfc_state%SSS(i,j) + dh * CS%tv%S(i,j,k) + sfc_state%SST(i,j) = sfc_state%SST(i,j) + dh * US%C_to_degC*CS%tv%T(i,j,k) + sfc_state%SSS(i,j) = sfc_state%SSS(i,j) + dh * US%S_to_ppt*CS%tv%S(i,j,k) else sfc_state%sfc_density(i,j) = sfc_state%sfc_density(i,j) + dh * GV%Rlay(k) endif @@ -3323,8 +3320,8 @@ subroutine extract_surface_state(CS, sfc_state_in) I_depth = 1.0 / (GV%H_subroundoff*H_rescale) missing_depth = GV%H_subroundoff*H_rescale - depth(i) if (use_temperature) then - sfc_state%SST(i,j) = (sfc_state%SST(i,j) + missing_depth*CS%tv%T(i,j,1)) * I_depth - sfc_state%SSS(i,j) = (sfc_state%SSS(i,j) + missing_depth*CS%tv%S(i,j,1)) * I_depth + sfc_state%SST(i,j) = (sfc_state%SST(i,j) + missing_depth*US%C_to_degC*CS%tv%T(i,j,1)) * I_depth + sfc_state%SSS(i,j) = (sfc_state%SSS(i,j) + missing_depth*US%S_to_ppt*CS%tv%S(i,j,1)) * I_depth else sfc_state%sfc_density(i,j) = (sfc_state%sfc_density(i,j) + & missing_depth*GV%Rlay(1)) * I_depth @@ -3408,28 +3405,37 @@ subroutine extract_surface_state(CS, sfc_state_in) if (allocated(sfc_state%melt_potential)) then - !$OMP parallel do default(shared) private(depth_ml, dh, T_freeze, depth, delT) + !$OMP parallel do default(shared) private(depth_ml, dh, T_freeze, depth, pres, delT) do j=js,je do i=is,ie depth(i) = 0.0 delT(i) = 0.0 + pres(i) = 0.0 + ! Here it is assumed that p=0 is OK, since HFrz ~ 10 to 20m, but under ice-shelves this + ! can be a very bad assumption. ###To fix this, uncomment the following... + ! pres(i) = p_surface(i) + 0.5*(GV%g_Earth*GV%H_to_RZ)*h(i,j,1) enddo - do k=1,nz ; do i=is,ie - depth_ml = min(CS%HFrz, CS%visc%MLD(i,j)) - if (depth(i) + h(i,j,k)*GV%H_to_Z < depth_ml) then - dh = h(i,j,k)*GV%H_to_Z - elseif (depth(i) < depth_ml) then - dh = depth_ml - depth(i) - else - dh = 0.0 - endif + do k=1,nz + call calculate_TFreeze(CS%tv%S(is:ie,j,k), pres(is:ie), T_freeze(is:ie), CS%tv%eqn_of_state) + do i=is,ie + depth_ml = min(CS%HFrz, CS%visc%MLD(i,j)) + if (depth(i) + h(i,j,k)*GV%H_to_Z < depth_ml) then + dh = h(i,j,k)*GV%H_to_Z + elseif (depth(i) < depth_ml) then + dh = depth_ml - depth(i) + else + dh = 0.0 + endif - ! p=0 OK, HFrz ~ 10 to 20m - call calculate_TFreeze(CS%tv%S(i,j,k), 0.0, T_freeze, CS%tv%eqn_of_state) - depth(i) = depth(i) + dh - delT(i) = delT(i) + dh * (CS%tv%T(i,j,k) - T_freeze) - enddo ; enddo + depth(i) = depth(i) + dh + delT(i) = delT(i) + dh * (CS%tv%T(i,j,k) - T_freeze(i)) + enddo + ! If there is a pressure-dependent freezing point calculation uncomment the following. + ! if (k m s-1] real, dimension(:,:,:), intent(in) :: v_in !< Meridional velocity on the initial grid [L T-1 ~> m s-1] real, dimension(:,:,:), intent(in) :: h_in !< Layer thickness on the initial grid [H ~> m or kg m-2] - real, dimension(:,:,:), intent(in) :: T_in !< Temperature on the initial grid [degC] - real, dimension(:,:,:), intent(in) :: S_in !< Salinity on the initial grid [ppt] + real, dimension(:,:,:), intent(in) :: T_in !< Temperature on the initial grid [C ~> degC] + real, dimension(:,:,:), intent(in) :: S_in !< Salinity on the initial grid [S ~> ppt] logical, intent(in) :: use_temperature !< If true, temperature and salinity are active integer, intent(in) :: turns !< The number quarter-turns to apply real, dimension(:,:,:), intent(out) :: u !< Zonal velocity on the rotated grid [L T-1 ~> m s-1] real, dimension(:,:,:), intent(out) :: v !< Meridional velocity on the rotated grid [L T-1 ~> m s-1] real, dimension(:,:,:), intent(out) :: h !< Layer thickness on the rotated grid [H ~> m or kg m-2] - real, dimension(:,:,:), intent(out) :: T !< Temperature on the rotated grid [degC] - real, dimension(:,:,:), intent(out) :: S !< Salinity on the rotated grid [ppt] + real, dimension(:,:,:), intent(out) :: T !< Temperature on the rotated grid [C ~> degC] + real, dimension(:,:,:), intent(out) :: S !< Salinity on the rotated grid [S ~> ppt] call rotate_vector(u_in, v_in, turns, u, v) call rotate_array(h_in, turns, h) @@ -3643,8 +3649,8 @@ subroutine get_MOM_state_elements(CS, G, GV, US, C_p, C_p_scaled, use_temp) if (present(G)) G => CS%G_in if (present(GV)) GV => CS%GV if (present(US)) US => CS%US - if (present(C_p)) C_p = CS%US%Q_to_J_kg * CS%tv%C_p - if (present(C_p_scaled)) C_p_scaled = CS%tv%C_p + if (present(C_p)) C_p = CS%US%Q_to_J_kg*US%degC_to_C * CS%tv%C_p + if (present(C_p_scaled)) C_p_scaled = US%degC_to_C*CS%tv%C_p if (present(use_temp)) use_temp = associated(CS%tv%T) end subroutine get_MOM_state_elements @@ -3659,9 +3665,10 @@ 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 * global_mass_integral(CS%h, CS%G, CS%GV, CS%tv%T, on_PE_only=on_PE_only) + heat = CS%US%Q_to_J_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) + salt = 1.0e-3 * global_mass_integral(CS%h, CS%G, CS%GV, CS%tv%S, on_PE_only=on_PE_only, scale=CS%US%S_to_ppt) end subroutine get_ocean_stocks diff --git a/src/core/MOM_PressureForce_FV.F90 b/src/core/MOM_PressureForce_FV.F90 index 2a79486a5f..e66732c50d 100644 --- a/src/core/MOM_PressureForce_FV.F90 +++ b/src/core/MOM_PressureForce_FV.F90 @@ -98,14 +98,14 @@ subroutine PressureForce_FV_nonBouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_ real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: p ! Interface pressure [R L2 T-2 ~> Pa]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), target :: & T_tmp, & ! Temporary array of temperatures where layers that are lighter - ! than the mixed layer have the mixed layer's properties [degC]. + ! than the mixed layer have the mixed layer's properties [C ~> degC]. S_tmp ! Temporary array of salinities where layers that are lighter - ! than the mixed layer have the mixed layer's properties [ppt]. + ! than the mixed layer have the mixed layer's properties [S ~> ppt]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: & S_t, & ! Top and bottom edge values for linear reconstructions - S_b, & ! of salinity within each layer [ppt]. + S_b, & ! of salinity within each layer [S ~> ppt]. T_t, & ! Top and bottom edge values for linear reconstructions - T_b ! of temperature within each layer [degC]. + T_b ! of temperature within each layer [C ~> degC]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: & dza, & ! The change in geopotential anomaly between the top and bottom ! of a layer [L2 T-2 ~> m2 s-2]. @@ -467,12 +467,14 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), target :: & T_tmp, & ! Temporary array of temperatures where layers that are lighter - ! than the mixed layer have the mixed layer's properties [degC]. + ! than the mixed layer have the mixed layer's properties [C ~> degC]. S_tmp ! Temporary array of salinities where layers that are lighter - ! than the mixed layer have the mixed layer's properties [ppt]. + ! than the mixed layer have the mixed layer's properties [S ~> ppt]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: & - S_t, S_b, T_t, T_b ! Top and bottom edge values for linear reconstructions - ! of salinity and temperature within each layer. + S_t, & ! Top and bottom edge values for linear reconstructions + S_b, & ! of salinity within each layer [S ~> ppt]. + T_t, & ! Top and bottom edge values for linear reconstructions + T_b ! of temperature within each layer [C ~> degC]. real :: rho_in_situ(SZI_(G)) ! The in situ density [R ~> kg m-3]. real :: p_ref(SZI_(G)) ! The pressure used to calculate the coordinate ! density, [R L2 T-2 ~> Pa] (usually 2e7 Pa = 2000 dbar). @@ -487,9 +489,9 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm logical :: use_ALE ! If true, use an ALE pressure reconstruction. logical :: use_EOS ! If true, density is calculated from T & S using an equation of state. type(thermo_var_ptrs) :: tv_tmp! A structure of temporary T & S. - real :: Tl(5) ! copy and T in local stencil [degC] - real :: mn_T ! mean of T in local stencil [degC] - real :: mn_T2 ! mean of T**2 in local stencil [degC2] + real :: Tl(5) ! copy and T in local stencil [C ~> degC] + real :: mn_T ! mean of T in local stencil [C ~> degC] + real :: mn_T2 ! mean of T**2 in local stencil [C2 ~> degC2] real :: hl(5) ! Copy of local stencil of H [H ~> m] real :: r_sm_H ! Reciprocal of sum of H in local stencil [H-1 ~> m-1] real, parameter :: C1_6 = 1.0/6.0 @@ -520,11 +522,11 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm ! This block calculates a simple |delta T| along coordinates and does ! not allow vanishing layer thicknesses or layers tracking topography - !! SGS variance in i-direction [degC2] + !! SGS variance in i-direction [C2 ~> degC2] !dTdi2 = ( ( G%mask2dCu(I ,j) * G%IdxCu(I ,j) * ( tv%T(i+1,j,k) - tv%T(i,j,k) ) & ! + G%mask2dCu(I-1,j) * G%IdxCu(I-1,j) * ( tv%T(i,j,k) - tv%T(i-1,j,k) ) & ! ) * G%dxT(i,j) * 0.5 )**2 - !! SGS variance in j-direction [degC2] + !! SGS variance in j-direction [C2 ~> degC2] !dTdj2 = ( ( G%mask2dCv(i,J ) * G%IdyCv(i,J ) * ( tv%T(i,j+1,k) - tv%T(i,j,k) ) & ! + G%mask2dCv(i,J-1) * G%IdyCv(i,J-1) * ( tv%T(i,j,k) - tv%T(i,j-1,k) ) & ! ) * G%dyT(i,j) * 0.5 )**2 @@ -699,7 +701,7 @@ subroutine PressureForce_FV_Bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm ! where the layers are located. if ( use_ALE .and. CS%Recon_Scheme > 0 ) then if ( CS%Recon_Scheme == 1 ) then - call int_density_dz_generic_plm(k, tv, T_t, T_b, S_t, S_b, e, & + call int_density_dz_generic_plm(k, tv, T_t, T_b, S_t, S_b, e, & rho_ref, CS%Rho0, GV%g_Earth, dz_neglect, G%bathyT, & G%HI, GV, tv%eqn_of_state, US, dpa, intz_dpa, intx_dpa, inty_dpa, & useMassWghtInterp=CS%useMassWghtInterp, & @@ -866,7 +868,7 @@ subroutine PressureForce_FV_init(Time, G, GV, US, param_file, diag, CS, tides_CS "Negative values disable the scheme.", units="nondim", default=-1.0) if (CS%Stanley_T2_det_coeff>=0.) then CS%id_tvar_sgs = register_diag_field('ocean_model', 'tvar_sgs_pgf', diag%axesTL, & - Time, 'SGS temperature variance used in PGF', 'degC2') + Time, 'SGS temperature variance used in PGF', 'degC2', conversion=US%C_to_degC**2) endif if (CS%tides) then CS%id_e_tidal = register_diag_field('ocean_model', 'e_tidal', diag%axesT1, & diff --git a/src/core/MOM_PressureForce_Montgomery.F90 b/src/core/MOM_PressureForce_Montgomery.F90 index 7d20409453..003bd2c3ec 100644 --- a/src/core/MOM_PressureForce_Montgomery.F90 +++ b/src/core/MOM_PressureForce_Montgomery.F90 @@ -91,9 +91,9 @@ subroutine PressureForce_Mont_nonBouss(h, tv, PFu, PFv, G, GV, US, CS, p_atm, pb ! in seawater, but p will still be close to the pressure. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), target :: & T_tmp, & ! Temporary array of temperatures where layers that are lighter - ! than the mixed layer have the mixed layer's properties [degC]. + ! than the mixed layer have the mixed layer's properties [C ~> degC]. S_tmp ! Temporary array of salinities where layers that are lighter - ! than the mixed layer have the mixed layer's properties [ppt]. + ! than the mixed layer have the mixed layer's properties [S ~> ppt]. real, dimension(SZI_(G)) :: Rho_cv_BL ! The coordinate potential density in the ! deepest variable density near-surface layer [R ~> kg m-3]. @@ -386,9 +386,9 @@ subroutine PressureForce_Mont_Bouss(h, tv, PFu, PFv, G, GV, US, CS, p_atm, pbce, ! in seawater, but e will still be close to the interface depth. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), target :: & T_tmp, & ! Temporary array of temperatures where layers that are lighter - ! than the mixed layer have the mixed layer's properties [degC]. + ! than the mixed layer have the mixed layer's properties [C ~> degC]. S_tmp ! Temporary array of salinities where layers that are lighter - ! than the mixed layer have the mixed layer's properties [ppt]. + ! than the mixed layer have the mixed layer's properties [S ~> ppt]. real :: Rho_cv_BL(SZI_(G)) ! The coordinate potential density in ! the deepest variable density near-surface layer [R ~> kg m-3]. @@ -626,10 +626,10 @@ subroutine Set_pbce_Bouss(e, tv, G, GV, US, Rho0, GFS_scale, pbce, rho_star) ! Local variables real :: Ihtot(SZI_(G)) ! The inverse of the sum of the layer thicknesses [H-1 ~> m-1 or m2 kg-1]. real :: press(SZI_(G)) ! Interface pressure [R L2 T-2 ~> Pa]. - real :: T_int(SZI_(G)) ! Interface temperature [degC]. - real :: S_int(SZI_(G)) ! Interface salinity [ppt]. - real :: dR_dT(SZI_(G)) ! Partial derivative of density with temperature [R degC-1 ~> kg m-3 degC-1]. - real :: dR_dS(SZI_(G)) ! Partial derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1]. + real :: T_int(SZI_(G)) ! Interface temperature [C ~> degC] + real :: S_int(SZI_(G)) ! Interface salinity [S ~> ppt] + real :: dR_dT(SZI_(G)) ! Partial derivative of density with temperature [R C-1 ~> kg m-3 degC-1] + real :: dR_dS(SZI_(G)) ! Partial derivative of density with salinity [R S-1 ~> kg m-3 ppt-1]. real :: rho_in_situ(SZI_(G)) ! In-situ density at the top of a layer [R ~> kg m-3]. real :: G_Rho0 ! A scaled version of g_Earth / Rho0 [L2 Z-1 T-2 R-1 ~> m4 s-2 kg-1] real :: Rho0xG ! g_Earth * Rho0 [R L2 Z-1 T-2 ~> kg s-2 m-2] @@ -727,10 +727,10 @@ subroutine Set_pbce_nonBouss(p, tv, G, GV, US, GFS_scale, pbce, alpha_star) dpbce, & ! A barotropic correction to the pbce to enable the use of ! a reduced gravity form of the equations [L2 H-1 T-2 ~> m4 kg-1 s-2]. C_htot ! dP_dH divided by the total ocean pressure [H-1 ~> m2 kg-1]. - real :: T_int(SZI_(G)) ! Interface temperature [degC]. - real :: S_int(SZI_(G)) ! Interface salinity [ppt]. - real :: dR_dT(SZI_(G)) ! Partial derivative of density with temperature [R degC-1 ~> kg m-3 degC-1]. - real :: dR_dS(SZI_(G)) ! Partial derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1]. + real :: T_int(SZI_(G)) ! Interface temperature [C ~> degC] + real :: S_int(SZI_(G)) ! Interface salinity [S ~> ppt] + real :: dR_dT(SZI_(G)) ! Partial derivative of density with temperature [R C-1 ~> kg m-3 degC-1] + real :: dR_dS(SZI_(G)) ! Partial derivative of density with salinity [R S-1 ~> kg m-3 ppt-1]. real :: rho_in_situ(SZI_(G)) ! In-situ density at an interface [R ~> kg m-3]. real :: alpha_Lay(SZK_(GV)) ! The specific volume of each layer [R-1 ~> m3 kg-1]. real :: dalpha_int(SZK_(GV)+1) ! The change in specific volume across each interface [R-1 ~> m3 kg-1]. diff --git a/src/core/MOM_checksum_packages.F90 b/src/core/MOM_checksum_packages.F90 index d9855a98d3..bc6f206b33 100644 --- a/src/core/MOM_checksum_packages.F90 +++ b/src/core/MOM_checksum_packages.F90 @@ -124,12 +124,12 @@ subroutine MOM_thermo_chksum(mesg, tv, G, US, haloshift) integer :: hs hs=1 ; if (present(haloshift)) hs=haloshift - if (associated(tv%T)) call hchksum(tv%T, mesg//" T", G%HI, haloshift=hs) - if (associated(tv%S)) call hchksum(tv%S, mesg//" S", G%HI, haloshift=hs) + if (associated(tv%T)) call hchksum(tv%T, mesg//" T", G%HI, haloshift=hs, scale=US%C_to_degC) + if (associated(tv%S)) call hchksum(tv%S, mesg//" S", G%HI, haloshift=hs, scale=US%S_to_ppt) if (associated(tv%frazil)) call hchksum(tv%frazil, mesg//" frazil", G%HI, haloshift=hs, & scale=US%Q_to_J_kg*US%R_to_kg_m3*US%Z_to_m) - if (associated(tv%salt_deficit)) & - call hchksum(tv%salt_deficit, mesg//" salt deficit", G%HI, haloshift=hs, scale=US%RZ_to_kg_m2) + if (associated(tv%salt_deficit)) call hchksum(tv%salt_deficit, mesg//" salt deficit", G%HI, haloshift=hs, & + scale=US%S_to_ppt*US%RZ_to_kg_m2) end subroutine MOM_thermo_chksum @@ -240,9 +240,9 @@ subroutine MOM_state_stats(mesg, u, v, h, Temp, Salt, G, GV, US, allowChange, pe real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]. real, pointer, dimension(:,:,:), & - intent(in) :: Temp !< Temperature [degC]. + intent(in) :: Temp !< Temperature [C ~> degC]. real, pointer, dimension(:,:,:), & - intent(in) :: Salt !< Salinity [ppt]. + intent(in) :: Salt !< Salinity [S ~> ppt]. type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type logical, optional, intent(in) :: allowChange !< do not flag an error !! if the statistics change. @@ -258,8 +258,11 @@ subroutine MOM_state_stats(mesg, u, v, h, Temp, Salt, G, GV, US, allowChange, pe real :: Vol, dV ! The total ocean volume and its change [m3] (unscaled to permit reproducing sum). real :: Area ! The total ocean surface area [m2] (unscaled to permit reproducing sum). real :: h_minimum ! The minimum layer thicknesses [H ~> m or kg m-2] + real :: T_scale ! The scaling conversion factor for temperatures [degC C-1 ~> 1] + real :: S_scale ! The scaling conversion factor for salinities [ppt S-1 ~> 1] logical :: do_TS ! If true, evaluate statistics for temperature and salinity - type(stats) :: T, S, delT, delS + type(stats) :: T, delT ! Temperature statistics in unscaled units [degC] + type(stats) :: S, delS ! Salinity statistics in unscaled units [ppt] ! NOTE: save data is not normally allowed but we use it for debugging purposes here on the ! assumption we will not turn this on with threads @@ -278,6 +281,8 @@ subroutine MOM_state_stats(mesg, u, v, h, Temp, Salt, G, GV, US, allowChange, pe tmp_T(:,:) = 0.0 tmp_S(:,:) = 0.0 + T_scale = US%C_to_degC ; S_scale = US%S_to_ppt + ! First collect local stats do j=js,je ; do i=is,ie tmp_A(i,j) = tmp_A(i,j) + US%L_to_m**2*G%areaT(i,j) @@ -290,12 +295,12 @@ subroutine MOM_state_stats(mesg, u, v, h, Temp, Salt, G, GV, US, allowChange, pe dV = US%L_to_m**2*G%areaT(i,j)*GV%H_to_m*h(i,j,k) tmp_V(i,j) = tmp_V(i,j) + dV if (do_TS .and. h(i,j,k)>0.) then - T%minimum = min( T%minimum, Temp(i,j,k) ) ; T%maximum = max( T%maximum, Temp(i,j,k) ) - T%average = T%average + dV*Temp(i,j,k) - S%minimum = min( S%minimum, Salt(i,j,k) ) ; S%maximum = max( S%maximum, Salt(i,j,k) ) - S%average = S%average + dV*Salt(i,j,k) - tmp_T(i,j) = tmp_T(i,j) + dV*Temp(i,j,k) - tmp_S(i,j) = tmp_S(i,j) + dV*Salt(i,j,k) + T%minimum = min( T%minimum, T_scale*Temp(i,j,k) ) ; T%maximum = max( T%maximum, T_scale*Temp(i,j,k) ) + T%average = T%average + dV*T_scale*Temp(i,j,k) + S%minimum = min( S%minimum, S_scale*Salt(i,j,k) ) ; S%maximum = max( S%maximum, S_scale*Salt(i,j,k) ) + S%average = S%average + dV*S_scale*Salt(i,j,k) + tmp_T(i,j) = tmp_T(i,j) + dV*T_scale*Temp(i,j,k) + tmp_S(i,j) = tmp_S(i,j) + dV*S_scale*Salt(i,j,k) endif if (h_minimum > h(i,j,k)) h_minimum = h(i,j,k) endif @@ -343,11 +348,11 @@ subroutine MOM_state_stats(mesg, u, v, h, Temp, Salt, G, GV, US, allowChange, pe if (do_TS .and. T%minimum<-5.0) then do j=js,je ; do i=is,ie - if (minval(Temp(i,j,:)) == T%minimum) then + if (minval(T_scale*Temp(i,j,:)) == T%minimum) then write(0,'(a,2f12.5)') 'x,y=', G%geoLonT(i,j), G%geoLatT(i,j) write(0,'(a3,3a12)') 'k','h','Temp','Salt' do k = 1, nz - write(0,'(i3,3es12.4)') k, h(i,j,k), Temp(i,j,k), Salt(i,j,k) + write(0,'(i3,3es12.4)') k, h(i,j,k), T_scale*Temp(i,j,k), S_scale*Salt(i,j,k) enddo stop 'Extremum detected' endif @@ -360,7 +365,7 @@ subroutine MOM_state_stats(mesg, u, v, h, Temp, Salt, G, GV, US, allowChange, pe write(0,'(a,2f12.5)') 'x,y=',G%geoLonT(i,j),G%geoLatT(i,j) write(0,'(a3,3a12)') 'k','h','Temp','Salt' do k = 1, nz - write(0,'(i3,3es12.4)') k, h(i,j,k), Temp(i,j,k), Salt(i,j,k) + write(0,'(i3,3es12.4)') k, h(i,j,k), T_scale*Temp(i,j,k), S_scale*Salt(i,j,k) enddo stop 'Negative thickness detected' endif diff --git a/src/core/MOM_density_integrals.F90 b/src/core/MOM_density_integrals.F90 index cfb61e897b..a617ee514d 100644 --- a/src/core/MOM_density_integrals.F90 +++ b/src/core/MOM_density_integrals.F90 @@ -40,9 +40,9 @@ subroutine int_density_dz(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, EOS, US, dpa, intz_dpa, intx_dpa, inty_dpa, bathyT, dz_neglect, useMassWghtInterp, Z_0p) type(hor_index_type), intent(in) :: HI !< Ocean horizontal index structures for the arrays real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: T !< Potential temperature referenced to the surface [degC] + intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: S !< Salinity [ppt] + intent(in) :: S !< Salinity [S ~> ppt] real, dimension(SZI_(HI),SZJ_(HI)), & intent(in) :: z_t !< Height at the top of the layer in depth units [Z ~> m] real, dimension(SZI_(HI),SZJ_(HI)), & @@ -97,9 +97,9 @@ subroutine int_density_dz_generic_pcm(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, & dz_neglect, useMassWghtInterp, use_inaccurate_form, Z_0p) type(hor_index_type), intent(in) :: HI !< Horizontal index type for input variables. real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: T !< Potential temperature of the layer [degC] + intent(in) :: T !< Potential temperature of the layer [C ~> degC] real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: S !< Salinity of the layer [ppt] + intent(in) :: S !< Salinity of the layer [S ~> ppt] real, dimension(SZI_(HI),SZJ_(HI)), & intent(in) :: z_t !< Height at the top of the layer in depth units [Z ~> m] real, dimension(SZI_(HI),SZJ_(HI)), & @@ -139,7 +139,7 @@ subroutine int_density_dz_generic_pcm(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, & real, optional, intent(in) :: Z_0p !< The height at which the pressure is 0 [Z ~> m] ! Local variables - real :: T5(5), S5(5) ! Temperatures and salinities at five quadrature points [degC] and [ppt] + real :: T5(5), S5(5) ! Temperatures and salinities at five quadrature points [C ~> degC] and [S ~> ppt] real :: p5(5) ! Pressures at five quadrature points [R L2 T-2 ~> Pa] real :: r5(5) ! Densities at five quadrature points [R ~> kg m-3] real :: rho_anom ! The depth averaged density anomaly [R ~> kg m-3] @@ -317,13 +317,13 @@ subroutine int_density_dz_generic_plm(k, tv, T_t, T_b, S_t, S_b, e, rho_ref, & type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), & - intent(in) :: T_t !< Potential temperature at the cell top [degC] + intent(in) :: T_t !< Potential temperature at the cell top [C ~> degC] real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), & - intent(in) :: T_b !< Potential temperature at the cell bottom [degC] + intent(in) :: T_b !< Potential temperature at the cell bottom [C ~> degC] real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), & - intent(in) :: S_t !< Salinity at the cell top [ppt] + intent(in) :: S_t !< Salinity at the cell top [S ~> ppt] real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), & - intent(in) :: S_b !< Salinity at the cell bottom [ppt] + intent(in) :: S_b !< Salinity at the cell bottom [S ~> ppt] real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)+1), & intent(in) :: e !< Height of interfaces [Z ~> m] real, intent(in) :: rho_ref !< A mean density [R ~> kg m-3], that is subtracted @@ -368,21 +368,26 @@ subroutine int_density_dz_generic_plm(k, tv, T_t, T_b, S_t, S_b, e, rho_ref, & ! a linear interpolation is used to compute intermediate values. ! Local variables - real :: T5((5*HI%iscB+1):(5*(HI%iecB+2))) ! Temperatures along a line of subgrid locations [degC] - real :: S5((5*HI%iscB+1):(5*(HI%iecB+2))) ! Salinities along a line of subgrid locations [ppt] - real :: T25((5*HI%iscB+1):(5*(HI%iecB+2))) ! SGS temperature variance along a line of subgrid locations [degC2] - real :: TS5((5*HI%iscB+1):(5*(HI%iecB+2))) ! SGS temp-salt covariance along a line of subgrid locations [degC ppt] - real :: S25((5*HI%iscB+1):(5*(HI%iecB+2))) ! SGS salinity variance along a line of subgrid locations [ppt2] + real :: T5((5*HI%iscB+1):(5*(HI%iecB+2))) ! Temperatures along a line of subgrid locations [C ~> degC] + real :: S5((5*HI%iscB+1):(5*(HI%iecB+2))) ! Salinities along a line of subgrid locations [S ~> ppt] + real :: T25((5*HI%iscB+1):(5*(HI%iecB+2))) ! SGS temperature variance along a line of subgrid + ! locations [C2 ~> degC2] + real :: TS5((5*HI%iscB+1):(5*(HI%iecB+2))) ! SGS temp-salt covariance along a line of subgrid + ! locations [C S ~> degC ppt] + real :: S25((5*HI%iscB+1):(5*(HI%iecB+2))) ! SGS salinity variance along a line of subgrid locations [S2 ~> ppt2] real :: p5((5*HI%iscB+1):(5*(HI%iecB+2))) ! Pressures along a line of subgrid locations [R L2 T-2 ~> Pa] real :: r5((5*HI%iscB+1):(5*(HI%iecB+2))) ! Densities anomalies along a line of subgrid ! locations [R ~> kg m-3] real :: u5((5*HI%iscB+1):(5*(HI%iecB+2))) ! Densities anomalies along a line of subgrid locations ! (used for inaccurate form) [R ~> kg m-3] - real :: T15((15*HI%iscB+1):(15*(HI%iecB+1))) ! Temperatures at an array of subgrid locations [degC] - real :: S15((15*HI%iscB+1):(15*(HI%iecB+1))) ! Salinities at an array of subgrid locations [ppt] - real :: T215((15*HI%iscB+1):(15*(HI%iecB+1))) ! SGS temperature variance along a line of subgrid locations [degC2] - real :: TS15((15*HI%iscB+1):(15*(HI%iecB+1))) ! SGS temp-salt covariance along a line of subgrid locations [degC ppt] - real :: S215((15*HI%iscB+1):(15*(HI%iecB+1))) ! SGS salinity variance along a line of subgrid locations [ppt2] + real :: T15((15*HI%iscB+1):(15*(HI%iecB+1))) ! Temperatures at an array of subgrid locations [C ~> degC] + real :: S15((15*HI%iscB+1):(15*(HI%iecB+1))) ! Salinities at an array of subgrid locations [S ~> ppt] + real :: T215((15*HI%iscB+1):(15*(HI%iecB+1))) ! SGS temperature variance along a line of subgrid + ! locations [C2 ~> degC2] + real :: TS15((15*HI%iscB+1):(15*(HI%iecB+1))) ! SGS temp-salt covariance along a line of subgrid + ! locations [C S ~> degC ppt] + real :: S215((15*HI%iscB+1):(15*(HI%iecB+1))) ! SGS salinity variance along a line of subgrid + ! locations [S2 ~> ppt2] real :: p15((15*HI%iscB+1):(15*(HI%iecB+1))) ! Pressures at an array of subgrid locations [R L2 T-2 ~> Pa] real :: r15((15*HI%iscB+1):(15*(HI%iecB+1))) ! Densities at an array of subgrid locations [R ~> kg m-3] real :: wt_t(5), wt_b(5) ! Top and bottom weights [nondim] @@ -397,8 +402,8 @@ subroutine int_density_dz_generic_plm(k, tv, T_t, T_b, S_t, S_b, e, rho_ref, & real :: dz_x(5,HI%iscB:HI%iecB) ! Layer thicknesses along an x-line of subgrid locations [Z ~> m] real :: dz_y(5,HI%isc:HI%iec) ! Layer thicknesses along a y-line of subgrid locations [Z ~> m] real :: massWeightToggle ! A non-dimensional toggle factor (0 or 1) [nondim] - real :: Ttl, Tbl, Ttr, Tbr ! Temperatures at the velocity cell corners [degC] - real :: Stl, Sbl, Str, Sbr ! Salinities at the velocity cell corners [ppt] + real :: Ttl, Tbl, Ttr, Tbr ! Temperatures at the velocity cell corners [C ~> degC] + real :: Stl, Sbl, Str, Sbr ! Salinities at the velocity cell corners [S ~> ppt] real :: z0pres ! The height at which the pressure is zero [Z ~> m] real :: hWght ! A topographically limited thickness weight [Z ~> m] real :: hL, hR ! Thicknesses to the left and right [Z ~> m] @@ -712,13 +717,13 @@ subroutine int_density_dz_generic_ppm(k, tv, T_t, T_b, S_t, S_b, e, & type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), & - intent(in) :: T_t !< Potential temperature at the cell top [degC] + intent(in) :: T_t !< Potential temperature at the cell top [C ~> degC] real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), & - intent(in) :: T_b !< Potential temperature at the cell bottom [degC] + intent(in) :: T_b !< Potential temperature at the cell bottom [C ~> degC] real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), & - intent(in) :: S_t !< Salinity at the cell top [ppt] + intent(in) :: S_t !< Salinity at the cell top [S ~> ppt] real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), & - intent(in) :: S_b !< Salinity at the cell bottom [ppt] + intent(in) :: S_b !< Salinity at the cell bottom [S ~> ppt] real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)+1), & intent(in) :: e !< Height of interfaces [Z ~> m] real, intent(in) :: rho_ref !< A mean density [R ~> kg m-3], that is @@ -761,11 +766,11 @@ subroutine int_density_dz_generic_ppm(k, tv, T_t, T_b, S_t, S_b, e, & ! a parabolic interpolation is used to compute intermediate values. ! Local variables - real :: T5(5) ! Temperatures along a line of subgrid locations [degC] - real :: S5(5) ! Salinities along a line of subgrid locations [ppt] - real :: T25(5) ! SGS temperature variance along a line of subgrid locations [degC2] - real :: TS5(5) ! SGS temperature-salinity covariance along a line of subgrid locations [degC ppt] - real :: S25(5) ! SGS salinity variance along a line of subgrid locations [ppt2] + real :: T5(5) ! Temperatures along a line of subgrid locations [C ~> degC] + real :: S5(5) ! Salinities along a line of subgrid locations [S ~> ppt] + real :: T25(5) ! SGS temperature variance along a line of subgrid locations [C2 ~> degC2] + real :: TS5(5) ! SGS temperature-salinity covariance along a line of subgrid locations [C S ~> degC ppt] + real :: S25(5) ! SGS salinity variance along a line of subgrid locations [S2 ~> ppt2] real :: p5(5) ! Pressures at five quadrature points [R L2 T-2 ~> Pa] real :: r5(5) ! Density anomalies from rho_ref at quadrature points [R ~> kg m-3] real :: wt_t(5), wt_b(5) ! Top and bottom weights [nondim] @@ -778,12 +783,12 @@ subroutine int_density_dz_generic_ppm(k, tv, T_t, T_b, S_t, S_b, e, & real :: I_Rho ! The inverse of the Boussinesq density [R-1 ~> m3 kg-1] real :: dz ! Layer thicknesses at tracer points [Z ~> m] real :: massWeightToggle ! A non-dimensional toggle factor (0 or 1) [nondim] - real :: Ttl, Tbl, Tml, Ttr, Tbr, Tmr ! Temperatures at the velocity cell corners [degC] - real :: Stl, Sbl, Sml, Str, Sbr, Smr ! Salinities at the velocity cell corners [ppt] - real :: s6 ! PPM curvature coefficient for S [ppt] - real :: t6 ! PPM curvature coefficient for T [degC] - real :: T_top, T_mn, T_bot ! Left edge, cell mean and right edge values used in PPM reconstructions of T - real :: S_top, S_mn, S_bot ! Left edge, cell mean and right edge values used in PPM reconstructions of S + real :: Ttl, Tbl, Tml, Ttr, Tbr, Tmr ! Temperatures at the velocity cell corners [C ~> degC] + real :: Stl, Sbl, Sml, Str, Sbr, Smr ! Salinities at the velocity cell corners [S ~> ppt] + real :: s6 ! PPM curvature coefficient for S [S ~> ppt] + real :: t6 ! PPM curvature coefficient for T [C ~> degC] + real :: T_top, T_mn, T_bot ! Left edge, cell mean and right edge values used in PPM reconstructions of T [C ~> degC] + real :: S_top, S_mn, S_bot ! Left edge, cell mean and right edge values used in PPM reconstructions of S [S ~> ppt] real :: z0pres ! The height at which the pressure is zero [Z ~> m] real :: hWght ! A topographically limited thickness weight [Z ~> m] real :: hL, hR ! Thicknesses to the left and right [Z ~> m] @@ -1042,9 +1047,9 @@ subroutine int_specific_vol_dp(T, S, p_t, p_b, alpha_ref, HI, EOS, US, & bathyP, dP_tiny, useMassWghtInterp) type(hor_index_type), intent(in) :: HI !< The horizontal index structure real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: T !< Potential temperature referenced to the surface [degC] + intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: S !< Salinity [ppt] + intent(in) :: S !< Salinity [S ~> ppt] real, dimension(SZI_(HI),SZJ_(HI)), & intent(in) :: p_t !< Pressure at the top of the layer [R L2 T-2 ~> Pa] real, dimension(SZI_(HI),SZJ_(HI)), & @@ -1100,9 +1105,9 @@ subroutine int_spec_vol_dp_generic_pcm(T, S, p_t, p_b, alpha_ref, HI, EOS, US, d bathyP, dP_neglect, useMassWghtInterp) type(hor_index_type), intent(in) :: HI !< A horizontal index type structure. real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: T !< Potential temperature of the layer [degC] + intent(in) :: T !< Potential temperature of the layer [C ~> degC] real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: S !< Salinity of the layer [ppt] + intent(in) :: S !< Salinity of the layer [S ~> ppt] real, dimension(SZI_(HI),SZJ_(HI)), & intent(in) :: p_t !< Pressure atop the layer [R L2 T-2 ~> Pa] real, dimension(SZI_(HI),SZJ_(HI)), & @@ -1145,8 +1150,8 @@ subroutine int_spec_vol_dp_generic_pcm(T, S, p_t, p_b, alpha_ref, HI, EOS, US, d ! series for log(1-eps/1+eps) that assumes that |eps| < 0.34. ! Local variables - real :: T5(5) ! Temperatures at five quadrature points [degC] - real :: S5(5) ! Salinities at five quadrature points [ppt] + real :: T5(5) ! Temperatures at five quadrature points [C ~> degC] + real :: S5(5) ! Salinities at five quadrature points [S ~> ppt] real :: p5(5) ! Pressures at five quadrature points [R L2 T-2 ~> Pa] real :: a5(5) ! Specific volumes at five quadrature points [R-1 ~> m3 kg-1] real :: alpha_anom ! The depth averaged specific density anomaly [R-1 ~> m3 kg-1] @@ -1295,13 +1300,13 @@ subroutine int_spec_vol_dp_generic_plm(T_t, T_b, S_t, S_b, p_t, p_b, alpha_ref, intp_dza, intx_dza, inty_dza, useMassWghtInterp) type(hor_index_type), intent(in) :: HI !< A horizontal index type structure. real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: T_t !< Potential temperature at the top of the layer [degC] + intent(in) :: T_t !< Potential temperature at the top of the layer [C ~> degC] real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: T_b !< Potential temperature at the bottom of the layer [degC] + intent(in) :: T_b !< Potential temperature at the bottom of the layer [C ~> degC] real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: S_t !< Salinity at the top the layer [ppt] + intent(in) :: S_t !< Salinity at the top the layer [S ~> ppt] real, dimension(SZI_(HI),SZJ_(HI)), & - intent(in) :: S_b !< Salinity at the bottom the layer [ppt] + intent(in) :: S_b !< Salinity at the bottom the layer [S ~> ppt] real, dimension(SZI_(HI),SZJ_(HI)), & intent(in) :: p_t !< Pressure atop the layer [R L2 T-2 ~> Pa] real, dimension(SZI_(HI),SZJ_(HI)), & @@ -1342,17 +1347,17 @@ subroutine int_spec_vol_dp_generic_plm(T_t, T_b, S_t, S_b, p_t, p_b, alpha_ref, ! Boole's rule to do the horizontal integrals, and from a truncation in the ! series for log(1-eps/1+eps) that assumes that |eps| < 0.34. - real :: T5(5) ! Temperatures at five quadrature points [degC] - real :: S5(5) ! Salinities at five quadrature points [ppt] + real :: T5(5) ! Temperatures at five quadrature points [C ~> degC] + real :: S5(5) ! Salinities at five quadrature points [S ~> ppt] real :: p5(5) ! Pressures at five quadrature points [R L2 T-2 ~> Pa] real :: a5(5) ! Specific volumes at five quadrature points [R-1 ~> m3 kg-1] - real :: T15(15) ! Temperatures at fifteen interior quadrature points [degC] - real :: S15(15) ! Salinities at fifteen interior quadrature points [ppt] + real :: T15(15) ! Temperatures at fifteen interior quadrature points [C ~> degC] + real :: S15(15) ! Salinities at fifteen interior quadrature points [S ~> ppt] real :: p15(15) ! Pressures at fifteen quadrature points [R L2 T-2 ~> Pa] real :: a15(15) ! Specific volumes at fifteen quadrature points [R-1 ~> m3 kg-1] real :: wt_t(5), wt_b(5) ! Weights of top and bottom values at quadrature points [nondim] - real :: T_top, T_bot ! Horizontally interpolated temperature at the cell top and bottom [degC] - real :: S_top, S_bot ! Horizontally interpolated salinity at the cell top and bottom [ppt] + real :: T_top, T_bot ! Horizontally interpolated temperature at the cell top and bottom [C ~> degC] + real :: S_top, S_bot ! Horizontally interpolated salinity at the cell top and bottom [S ~> ppt] real :: P_top, P_bot ! Horizontally interpolated pressure at the cell top and bottom [R L2 T-2 ~> Pa] real :: alpha_anom ! The depth averaged specific density anomaly [R-1 ~> m3 kg-1] @@ -1522,10 +1527,10 @@ end subroutine int_spec_vol_dp_generic_plm !> Find the depth at which the reconstructed pressure matches P_tgt subroutine find_depth_of_pressure_in_cell(T_t, T_b, S_t, S_b, z_t, z_b, P_t, P_tgt, & rho_ref, G_e, EOS, US, P_b, z_out, z_tol) - real, intent(in) :: T_t !< Potential temperature at the cell top [degC] - real, intent(in) :: T_b !< Potential temperature at the cell bottom [degC] - real, intent(in) :: S_t !< Salinity at the cell top [ppt] - real, intent(in) :: S_b !< Salinity at the cell bottom [ppt] + real, intent(in) :: T_t !< Potential temperature at the cell top [C ~> degC] + real, intent(in) :: T_b !< Potential temperature at the cell bottom [C ~> degC] + real, intent(in) :: S_t !< Salinity at the cell top [S ~> ppt] + real, intent(in) :: S_b !< Salinity at the cell bottom [S ~> ppt] real, intent(in) :: z_t !< Absolute height of top of cell [Z ~> m] (Boussinesq ????) real, intent(in) :: z_b !< Absolute height of bottom of cell [Z ~> m] real, intent(in) :: P_t !< Anomalous pressure of top of cell, relative @@ -1604,10 +1609,10 @@ end subroutine find_depth_of_pressure_in_cell !> Returns change in anomalous pressure change from top to non-dimensional !! position pos between z_t and z_b [R L2 T-2 ~> Pa] real function frac_dp_at_pos(T_t, T_b, S_t, S_b, z_t, z_b, rho_ref, G_e, pos, EOS) - real, intent(in) :: T_t !< Potential temperature at the cell top [degC] - real, intent(in) :: T_b !< Potential temperature at the cell bottom [degC] - real, intent(in) :: S_t !< Salinity at the cell top [ppt] - real, intent(in) :: S_b !< Salinity at the cell bottom [ppt] + real, intent(in) :: T_t !< Potential temperature at the cell top [C ~> degC] + real, intent(in) :: T_b !< Potential temperature at the cell bottom [C ~> degC] + real, intent(in) :: S_t !< Salinity at the cell top [S ~> ppt] + real, intent(in) :: S_b !< Salinity at the cell bottom [S ~> ppt] real, intent(in) :: z_t !< The geometric height at the top of the layer [Z ~> m] real, intent(in) :: z_b !< The geometric height at the bottom of the layer [Z ~> m] real, intent(in) :: rho_ref !< A mean density [R ~> kg m-3], that is subtracted out to @@ -1621,8 +1626,8 @@ real function frac_dp_at_pos(T_t, T_b, S_t, S_b, z_t, z_b, rho_ref, G_e, pos, EO real :: dz ! Distance from the layer top [Z ~> m] real :: top_weight, bottom_weight ! Fractional weights at quadrature points [nondim] real :: rho_ave ! Average density [R ~> kg m-3] - real, dimension(5) :: T5 ! Temperatures at quadrature points [degC] - real, dimension(5) :: S5 ! Salinities at quadrature points [ppt] + real, dimension(5) :: T5 ! Temperatures at quadrature points [C ~> degC] + real, dimension(5) :: S5 ! Salinities at quadrature points [S ~> ppt] real, dimension(5) :: p5 ! Pressures at quadrature points [R L2 T-2 ~> Pa] real, dimension(5) :: rho5 ! Densities at quadrature points [R ~> kg m-3] integer :: n diff --git a/src/core/MOM_forcing_type.F90 b/src/core/MOM_forcing_type.F90 index 227623f5eb..b8e5fe6c49 100644 --- a/src/core/MOM_forcing_type.F90 +++ b/src/core/MOM_forcing_type.F90 @@ -415,7 +415,7 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & real, dimension(SZI_(G),SZK_(GV)), & intent(in) :: h !< layer thickness [H ~> m or kg m-2] real, dimension(SZI_(G),SZK_(GV)), & - intent(in) :: T !< layer temperatures [degC] + intent(in) :: T !< layer temperatures [C ~> degC] real, dimension(SZI_(G)), intent(out) :: netMassInOut !< net mass flux (non-Bouss) or volume flux !! (if Bouss) of water in/out of ocean over !! a time step [H ~> m or kg m-2] @@ -429,12 +429,12 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & !! (1) downwelling (penetrative) SW, !! (2) evaporation heat content, !! (since do not yet know evap temperature). - !! [degC H ~> degC m or degC kg m-2]. + !! [C H ~> degC m or degC kg m-2]. real, dimension(SZI_(G)), intent(out) :: net_salt !< surface salt flux into the ocean !! accumulated over a time step - !! [ppt H ~> ppt m or ppt kg m-2]. + !! [S H ~> ppt m or ppt kg m-2]. real, dimension(max(1,nsw),G%isd:G%ied), intent(out) :: pen_SW_bnd !< penetrating SW flux, split into bands. - !! [degC H ~> degC m or degC kg m-2] + !! [C H ~> degC m or degC kg m-2] !! and array size nsw x SZI_(G), where !! nsw=number of SW bands in pen_SW_bnd. !! This heat flux is not part of net_heat. @@ -445,32 +445,32 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & logical, intent(in) :: aggregate_FW !< For determining how to aggregate forcing. real, dimension(SZI_(G)), & optional, intent(out) :: nonpenSW !< Non-penetrating SW used in net_heat - !! [degC H ~> degC m or degC kg m-2]. + !! [C H ~> degC m or degC kg m-2]. !! Summed over SW bands when diagnosing nonpenSW. real, dimension(SZI_(G)), & optional, intent(out) :: net_Heat_rate !< Rate of net surface heating - !! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1]. + !! [C H T-1 ~> degC m s-1 or degC kg m-2 s-1]. real, dimension(SZI_(G)), & optional, intent(out) :: net_salt_rate !< Surface salt flux into the ocean - !! [ppt H T-1 ~> ppt m s-1 or ppt kg m-2 s-1]. + !! [S H T-1 ~> ppt m s-1 or ppt kg m-2 s-1]. real, dimension(SZI_(G)), & optional, intent(out) :: netmassInOut_rate !< Rate of net mass flux into the ocean !! [H T-1 ~> m s-1 or kg m-2 s-1]. real, dimension(max(1,nsw),G%isd:G%ied), & optional, intent(out) :: pen_sw_bnd_rate !< Rate of penetrative shortwave heating - !! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1]. + !! [C H T-1 ~> degC m s-1 or degC kg m-2 s-1]. ! local real :: htot(SZI_(G)) ! total ocean depth [H ~> m or kg m-2] - real :: Pen_sw_tot(SZI_(G)) ! sum across all bands of Pen_SW [degC H ~> degC m or degC kg m-2]. + real :: Pen_sw_tot(SZI_(G)) ! sum across all bands of Pen_SW [C H ~> degC m or degC kg m-2]. real :: pen_sw_tot_rate(SZI_(G)) ! Summed rate of shortwave heating across bands - ! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] + ! [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] real :: Ih_limit ! inverse depth at which surface fluxes start to be limited ! or 0 for no limiting [H-1 ~> m-1 or m2 kg-1] real :: scale ! scale scales away fluxes if depth < FluxRescaleDepth [nondim] - real :: I_Cp ! 1.0 / C_p [degC Q-1 ~> kg degC J-1] + real :: I_Cp ! 1.0 / C_p [C Q-1 ~> kg degC J-1] real :: I_Cp_Hconvert ! Unit conversion factors divided by the heat capacity - ! [degC H R-1 Z-1 Q-1 ~> degC m3 J-1 or kg degC J-1] + ! [C H R-1 Z-1 Q-1 ~> degC m3 J-1 or kg degC J-1] logical :: calculate_diags ! Indicate to calculate/update diagnostic arrays character(len=200) :: mesg integer :: is, ie, nz, i, k, n @@ -492,8 +492,8 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & !}BGR Ih_limit = 0.0 ; if (FluxRescaleDepth > 0.0) Ih_limit = 1.0 / FluxRescaleDepth - I_Cp = 1.0 / fluxes%C_p - I_Cp_Hconvert = 1.0 / (GV%H_to_RZ * fluxes%C_p) + I_Cp = 1.0 / tv%C_p + I_Cp_Hconvert = 1.0 / (GV%H_to_RZ * tv%C_p) is = G%isc ; ie = G%iec ; nz = GV%ke @@ -539,7 +539,7 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & scale = 1.0 ; if ((Ih_limit > 0.0) .and. (htot(i)*Ih_limit < 1.0)) scale = htot(i)*Ih_limit - ! Convert the penetrating shortwave forcing to (K * H) and reduce fluxes for shallow depths. + ! Convert the penetrating shortwave forcing to (C * H) and reduce fluxes for shallow depths. ! (H=m for Bouss, H=kg/m2 for non-Bouss) Pen_sw_tot(i) = 0.0 if (nsw >= 1) then @@ -705,7 +705,7 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & write(mesg,'("Penetrating shortwave of ",1pe17.10, & &" exceeds total shortwave of ",1pe17.10,& &" at ",1pg11.4,",E,",1pg11.4,"N.")') & - Pen_SW_tot(i), I_Cp_Hconvert*scale*dt * fluxes%sw(i,j), & + US%C_to_degC*Pen_SW_tot(i), US%C_to_degC*I_Cp_Hconvert*scale*dt * fluxes%sw(i,j), & G%geoLonT(i,j), G%geoLatT(i,j) call MOM_error(WARNING,mesg) endif @@ -729,9 +729,9 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & ! Boussinesq: (ppt * m) ! non-Bouss: (g/m^2) if (associated(fluxes%salt_flux)) then - Net_salt(i) = (scale * dt * (1000.0 * fluxes%salt_flux(i,j))) * GV%RZ_to_H + Net_salt(i) = (scale * dt * (1000.0*US%ppt_to_S * fluxes%salt_flux(i,j))) * GV%RZ_to_H !Repeat above code for 'rate' term - if (do_NSR) Net_salt_rate(i) = (scale * 1. * (1000.0 * fluxes%salt_flux(i,j))) * GV%RZ_to_H + if (do_NSR) Net_salt_rate(i) = (scale * 1. * (1000.0*US%ppt_to_S * fluxes%salt_flux(i,j))) * GV%RZ_to_H endif ! Diagnostics follow... @@ -742,9 +742,9 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & if (associated(fluxes%heat_content_massin)) then if (aggregate_FW) then if (netMassInOut(i) > 0.0) then ! net is "in" - fluxes%heat_content_massin(i,j) = -fluxes%C_p * netMassOut(i) * T(i,1) * GV%H_to_RZ / dt + fluxes%heat_content_massin(i,j) = -tv%C_p * netMassOut(i) * T(i,1) * GV%H_to_RZ / dt else ! net is "out" - fluxes%heat_content_massin(i,j) = fluxes%C_p * ( netMassInout(i) - netMassOut(i) ) * & + fluxes%heat_content_massin(i,j) = tv%C_p * ( netMassInout(i) - netMassOut(i) ) * & T(i,1) * GV%H_to_RZ / dt endif else @@ -757,9 +757,9 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & if (associated(fluxes%heat_content_massout)) then if (aggregate_FW) then if (netMassInOut(i) > 0.0) then ! net is "in" - fluxes%heat_content_massout(i,j) = fluxes%C_p * netMassOut(i) * T(i,1) * GV%H_to_RZ / dt + fluxes%heat_content_massout(i,j) = tv%C_p * netMassOut(i) * T(i,1) * GV%H_to_RZ / dt else ! net is "out" - fluxes%heat_content_massout(i,j) = -fluxes%C_p * ( netMassInout(i) - netMassOut(i) ) * & + fluxes%heat_content_massout(i,j) = -tv%C_p * ( netMassInout(i) - netMassOut(i) ) * & T(i,1) * GV%H_to_RZ / dt endif else @@ -776,7 +776,7 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & ! wait until MOM_diabatic_driver.F90. if (associated(fluxes%heat_content_lprec)) then if (fluxes%lprec(i,j) > 0.0) then - fluxes%heat_content_lprec(i,j) = fluxes%C_p*fluxes%lprec(i,j)*T(i,1) + fluxes%heat_content_lprec(i,j) = tv%C_p*fluxes%lprec(i,j)*T(i,1) else fluxes%heat_content_lprec(i,j) = 0.0 endif @@ -787,7 +787,7 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & ! and until we do so fprec is treated like lprec and enters at SST. -AJA if (associated(fluxes%heat_content_fprec)) then if (fluxes%fprec(i,j) > 0.0) then - fluxes%heat_content_fprec(i,j) = fluxes%C_p*fluxes%fprec(i,j)*T(i,1) + fluxes%heat_content_fprec(i,j) = tv%C_p*fluxes%fprec(i,j)*T(i,1) else fluxes%heat_content_fprec(i,j) = 0.0 endif @@ -796,7 +796,7 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & ! Following lprec and fprec, water flux due to sea ice melt (seaice_melt) enters at SST - GMM if (associated(fluxes%heat_content_icemelt)) then if (fluxes%seaice_melt(i,j) > 0.0) then - fluxes%heat_content_icemelt(i,j) = fluxes%C_p*fluxes%seaice_melt(i,j)*T(i,1) + fluxes%heat_content_icemelt(i,j) = tv%C_p*fluxes%seaice_melt(i,j)*T(i,1) else fluxes%heat_content_icemelt(i,j) = 0.0 endif @@ -807,7 +807,7 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & ! vprec < 0 means remove water from ocean; set heat_content_vprec in MOM_diabatic_driver.F90 if (associated(fluxes%heat_content_vprec)) then if (fluxes%vprec(i,j) > 0.0) then - fluxes%heat_content_vprec(i,j) = fluxes%C_p*fluxes%vprec(i,j)*T(i,1) + fluxes%heat_content_vprec(i,j) = tv%C_p*fluxes%vprec(i,j)*T(i,1) else fluxes%heat_content_vprec(i,j) = 0.0 endif @@ -821,7 +821,7 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & ! Condensation is assumed to drop into the ocean at the SST, just like lprec. if (associated(fluxes%heat_content_cond)) then if (fluxes%evap(i,j) > 0.0) then - fluxes%heat_content_cond(i,j) = fluxes%C_p*fluxes%evap(i,j)*T(i,1) + fluxes%heat_content_cond(i,j) = tv%C_p*fluxes%evap(i,j)*T(i,1) else fluxes%heat_content_cond(i,j) = 0.0 endif @@ -830,14 +830,14 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & ! Liquid runoff enters ocean at SST if land model does not provide runoff heat content. if (.not. useRiverHeatContent) then if (associated(fluxes%lrunoff) .and. associated(fluxes%heat_content_lrunoff)) then - fluxes%heat_content_lrunoff(i,j) = fluxes%C_p*fluxes%lrunoff(i,j)*T(i,1) + fluxes%heat_content_lrunoff(i,j) = tv%C_p*fluxes%lrunoff(i,j)*T(i,1) endif endif ! Icebergs enter ocean at SST if land model does not provide calving heat content. if (.not. useCalvingHeatContent) then if (associated(fluxes%frunoff) .and. associated(fluxes%heat_content_frunoff)) then - fluxes%heat_content_frunoff(i,j) = fluxes%C_p*fluxes%frunoff(i,j)*T(i,1) + fluxes%heat_content_frunoff(i,j) = tv%C_p*fluxes%frunoff(i,j)*T(i,1) endif endif @@ -870,7 +870,7 @@ subroutine extractFluxes2d(G, GV, US, fluxes, optics, nsw, dt, FluxRescaleDepth, real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: h !< layer thickness [H ~> m or kg m-2] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(in) :: T !< layer temperatures [degC] + intent(in) :: T !< layer temperatures [C ~> degC] real, dimension(SZI_(G),SZJ_(G)), intent(out) :: netMassInOut !< net mass flux (non-Bouss) or volume flux !! (if Bouss) of water in/out of ocean over !! a time step [H ~> m or kg m-2] @@ -883,11 +883,11 @@ subroutine extractFluxes2d(G, GV, US, fluxes, optics, nsw, dt, FluxRescaleDepth, !! (1) downwelling (penetrative) SW, !! (2) evaporation heat content, !! (since do not yet know temperature of evap). - !! [degC H ~> degC m or degC kg m-2] + !! [C H ~> degC m or degC kg m-2] real, dimension(SZI_(G),SZJ_(G)), intent(out) :: net_salt !< surface salt flux into the ocean accumulated - !! over a time step [ppt H ~> ppt m or ppt kg m-2] + !! over a time step [S H ~> ppt m or ppt kg m-2] real, dimension(max(1,nsw),G%isd:G%ied,G%jsd:G%jed), intent(out) :: pen_SW_bnd !< penetrating SW flux, by frequency - !! band [degC H ~> degC m or degC kg m-2] with array + !! band [C H ~> degC m or degC kg m-2] with array !! size nsw x SZI_(G), where nsw=number of SW bands !! in pen_SW_bnd. This heat flux is not in net_heat. type(thermo_var_ptrs), intent(inout) :: tv !< structure containing pointers to available @@ -921,29 +921,29 @@ subroutine calculateBuoyancyFlux1d(G, GV, US, fluxes, optics, nsw, h, Temp, Salt type(optics_type), pointer :: optics !< penetrating SW optics integer, intent(in) :: nsw !< The number of frequency bands of !! penetrating shortwave radiation - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< layer thickness [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Temp !< prognostic temp [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Salt !< salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< layer thickness [H ~> m or kg m-2] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Temp !< prognostic temp [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Salt !< salinity [S ~> ppt] type(thermo_var_ptrs), intent(inout) :: tv !< thermodynamics type integer, intent(in) :: j !< j-row to work on real, dimension(SZI_(G),SZK_(GV)+1), intent(out) :: buoyancyFlux !< buoyancy fluxes [L2 T-3 ~> m2 s-3] real, dimension(SZI_(G)), intent(out) :: netHeatMinusSW !< Surface heat flux excluding shortwave - !! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] + !! [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] real, dimension(SZI_(G)), intent(out) :: netSalt !< surface salt flux - !! [ppt H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] + !! [S H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] ! local variables real, dimension(SZI_(G)) :: netH ! net FW flux [H T-1 ~> m s-1 or kg m-2 s-1] real, dimension(SZI_(G)) :: netEvap ! net FW flux leaving ocean via evaporation ! [H T-1 ~> m s-1 or kg m-2 s-1] - real, dimension(SZI_(G)) :: netHeat ! net temp flux [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] + real, dimension(SZI_(G)) :: netHeat ! net temp flux [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] real, dimension(max(nsw,1), SZI_(G)) :: penSWbnd ! penetrating SW radiation by band ! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] real, dimension(SZI_(G)) :: pressure ! pressure at the surface [R L2 T-2 ~> Pa] - real, dimension(SZI_(G)) :: dRhodT ! density partial derivative wrt temp [R degC-1 ~> kg m-3 degC-1] - real, dimension(SZI_(G)) :: dRhodS ! density partial derivative wrt saln [R ppt-1 ~> kg m-3 ppt-1] + real, dimension(SZI_(G)) :: dRhodT ! density partial derivative wrt temp [R C-1 ~> kg m-3 degC-1] + real, dimension(SZI_(G)) :: dRhodS ! density partial derivative wrt saln [R S-1 ~> kg m-3 ppt-1] real, dimension(SZI_(G),SZK_(GV)+1) :: netPen ! The net penetrating shortwave radiation at each level - ! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] + ! [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] logical :: useRiverHeatContent logical :: useCalvingHeatContent @@ -966,7 +966,7 @@ subroutine calculateBuoyancyFlux1d(G, GV, US, fluxes, optics, nsw, h, Temp, Salt ! We aggregate the thermodynamic forcing for a time step into the following: ! netH = water added/removed via surface fluxes [H T-1 ~> m s-1 or kg m-2 s-1] ! netHeat = heat via surface fluxes [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] - ! netSalt = salt via surface fluxes [ppt H T-1 ~> ppt m s-1 or gSalt m-2 s-1] + ! netSalt = salt via surface fluxes [S H T-1 ~> ppt m s-1 or gSalt m-2 s-1] ! Note that unlike other calls to extractFLuxes1d() that return the time-integrated flux ! this call returns the rate because dt=1 (in arbitrary time units) call extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, 1.0, & @@ -1014,14 +1014,14 @@ subroutine calculateBuoyancyFlux2d(G, GV, US, fluxes, optics, h, Temp, Salt, tv, type(forcing), intent(inout) :: fluxes !< surface fluxes type(optics_type), pointer :: optics !< SW ocean optics real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< layer thickness [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Temp !< temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Salt !< salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Temp !< temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Salt !< salinity [S ~> ppt] type(thermo_var_ptrs), intent(inout) :: tv !< thermodynamics type real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), intent(inout) :: buoyancyFlux !< buoyancy fluxes [L2 T-3 ~> m2 s-3] real, dimension(SZI_(G),SZJ_(G)), intent(inout) :: netHeatMinusSW !< surface heat flux excluding shortwave - !! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] + !! [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] real, dimension(SZI_(G),SZJ_(G)), intent(inout) :: netSalt !< Net surface salt flux - !! [ppt H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] + !! [S H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] ! local variables integer :: j diff --git a/src/core/MOM_isopycnal_slopes.F90 b/src/core/MOM_isopycnal_slopes.F90 index 38a3544703..65b51ba310 100644 --- a/src/core/MOM_isopycnal_slopes.F90 +++ b/src/core/MOM_isopycnal_slopes.F90 @@ -63,26 +63,26 @@ subroutine calc_isoneutral_slopes(G, GV, US, h, e, tv, dt_kappa_smooth, & ! (This argument has been tested but for now serves no purpose.) !! of eta to m; US%Z_to_m by default. ! Local variables real, dimension(SZI_(G), SZJ_(G), SZK_(GV)) :: & - T, & ! The temperature [degC], with the values in + T, & ! The temperature [C ~> degC], with the values in ! in massless layers filled vertically by diffusion. - S !, & ! The filled salinity [ppt], with the values in + S !, & ! The filled salinity [S ~> ppt], with the values in ! in massless layers filled vertically by diffusion. ! Rho ! Density itself, when a nonlinear equation of state is not in use [R ~> kg m-3]. real, dimension(SZI_(G), SZJ_(G),SZK_(GV)+1) :: & pres ! The pressure at an interface [R L2 T-2 ~> Pa]. real, dimension(SZIB_(G)) :: & - drho_dT_u, & ! The derivative of density with temperature at u points [R degC-1 ~> kg m-3 degC-1]. - drho_dS_u ! The derivative of density with salinity at u points [R ppt-1 ~> kg m-3 ppt-1]. + drho_dT_u, & ! The derivative of density with temperature at u points [R C-1 ~> kg m-3 degC-1]. + drho_dS_u ! The derivative of density with salinity at u points [R S-1 ~> kg m-3 ppt-1]. real, dimension(SZI_(G)) :: & - drho_dT_v, & ! The derivative of density with temperature at v points [R degC-1 ~> kg m-3 degC-1]. - drho_dS_v ! The derivative of density with salinity at v points [R ppt-1 ~> kg m-3 ppt-1]. + drho_dT_v, & ! The derivative of density with temperature at v points [R C-1 ~> kg m-3 degC-1]. + drho_dS_v ! The derivative of density with salinity at v points [R S-1 ~> kg m-3 ppt-1]. real, dimension(SZIB_(G)) :: & - T_u, & ! Temperature on the interface at the u-point [degC]. - S_u, & ! Salinity on the interface at the u-point [ppt]. + T_u, & ! Temperature on the interface at the u-point [C ~> degC]. + S_u, & ! Salinity on the interface at the u-point [S ~> ppt]. pres_u ! Pressure on the interface at the u-point [R L2 T-2 ~> Pa]. real, dimension(SZI_(G)) :: & - T_v, & ! Temperature on the interface at the v-point [degC]. - S_v, & ! Salinity on the interface at the v-point [ppt]. + T_v, & ! Temperature on the interface at the v-point [C ~> degC]. + S_v, & ! Salinity on the interface at the v-point [S ~> ppt]. pres_v ! Pressure on the interface at the v-point [R L2 T-2 ~> Pa]. real :: drdiA, drdiB ! Along layer zonal- and meridional- potential density real :: drdjA, drdjB ! gradients in the layers above (A) and below (B) the @@ -341,8 +341,8 @@ subroutine calc_isoneutral_slopes(G, GV, US, h, e, tv, dt_kappa_smooth, & T_v(i) = 0.25*((T(i,j,k) + T(i,j+1,k)) + (T(i,j,k-1) + T(i,j+1,k-1))) S_v(i) = 0.25*((S(i,j,k) + S(i,j+1,k)) + (S(i,j,k-1) + S(i,j+1,k-1))) enddo - call calculate_density_derivs(T_v, S_v, pres_v, drho_dT_v, drho_dS_v, tv%eqn_of_state, & - EOSdom_v) + call calculate_density_derivs(T_v, S_v, pres_v, drho_dT_v, drho_dS_v, & + tv%eqn_of_state, EOSdom_v) endif do i=is,ie if (use_EOS) then @@ -435,12 +435,12 @@ subroutine vert_fill_TS(h, T_in, S_in, kappa_dt, T_f, S_f, G, GV, halo_here, lar 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)), intent(in) :: T_in !< Input temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: S_in !< Input salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: T_in !< Input temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: S_in !< Input salinity [S ~> ppt] real, intent(in) :: kappa_dt !< A vertical diffusivity to use for smoothing !! times a smoothing timescale [Z2 ~> m2]. - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T_f !< Filled temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S_f !< Filled salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T_f !< Filled temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S_f !< Filled salinity [S ~> ppt] integer, optional, intent(in) :: halo_here !< Number of halo points to work on, !! 0 by default logical, optional, intent(in) :: larger_h_denom !< Present and true, add a large diff --git a/src/core/MOM_open_boundary.F90 b/src/core/MOM_open_boundary.F90 index bd05a4da7a..b449e7c9a5 100644 --- a/src/core/MOM_open_boundary.F90 +++ b/src/core/MOM_open_boundary.F90 @@ -80,21 +80,28 @@ module MOM_open_boundary integer :: fid_dz !< handle from FMS associated with segment thicknesses on disk character(len=8) :: name !< a name identifier for the segment data real, allocatable :: buffer_src(:,:,:) !< buffer for segment data located at cell faces - !! and on the original vertical grid + !! and on the original vertical grid. The values for tracers should + !! have the same units as the field they are being applied to? integer :: nk_src !< Number of vertical levels in the source data real, allocatable :: dz_src(:,:,:) !< vertical grid cell spacing of the incoming segment !! data, set in [Z ~> m] then scaled to [H ~> m or kg m-2] - real, allocatable :: buffer_dst(:,:,:) !< buffer src data remapped to the target vertical grid - real :: value !< constant value if fid is equal to -1 + real, allocatable :: buffer_dst(:,:,:) !< buffer src data remapped to the target vertical grid. + !! The values for tracers should have the same units as the field + !! they are being applied to? + real :: value !< constant value if fid is equal to -1 end type OBC_segment_data_type !> Tracer on OBC segment data structure, for putting into a segment tracer registry. type, public :: OBC_segment_tracer_type - real, allocatable :: t(:,:,:) !< tracer concentration array + real, allocatable :: t(:,:,:) !< tracer concentration array in rescaled units, + !! like [S ~> ppt] for salinity. real :: OBC_inflow_conc = 0.0 !< tracer concentration for generic inflows character(len=32) :: name !< tracer name used for error messages type(tracer_type), pointer :: Tr => NULL() !< metadata describing the tracer - real, allocatable :: tres(:,:,:) !< tracer reservoir array + real, allocatable :: tres(:,:,:) !< tracer reservoir array in rescaled units, + !! like [S ~> ppt] for salinity. + real :: scale !< A scaling factor for converting the units of input + !! data, like [S ppt-1 ~> 1] for salinity. logical :: is_initialized !< reservoir values have been set when True end type OBC_segment_tracer_type @@ -298,8 +305,8 @@ module MOM_open_boundary real, allocatable :: rx_oblique(:,:,:) !< Array storage for oblique boundary condition restarts [L2 T-2 ~> m2 s-2] real, allocatable :: ry_oblique(:,:,:) !< Array storage for oblique boundary condition restarts [L2 T-2 ~> m2 s-2] real, allocatable :: cff_normal(:,:,:) !< Array storage for oblique boundary condition restarts [L2 T-2 ~> m2 s-2] - real, allocatable :: tres_x(:,:,:,:) !< Array storage of tracer reservoirs for restarts [conc L ~> conc m] - real, allocatable :: tres_y(:,:,:,:) !< Array storage of tracer reservoirs for restarts [conc L ~> conc m] + real, allocatable :: tres_x(:,:,:,:) !< Array storage of tracer reservoirs for restarts, in unscaled units [conc] + real, allocatable :: tres_y(:,:,:,:) !< Array storage of tracer reservoirs for restarts, in unscaled units [conc] real :: silly_h !< A silly value of thickness outside of the domain that can be used to test !! the independence of the OBCs to this external data [H ~> m or kg m-2]. real :: silly_u !< A silly value of velocity outside of the domain that can be used to test @@ -1993,6 +2000,8 @@ subroutine setup_OBC_tracer_reservoirs(G, GV, OBC) type(ocean_OBC_type), target, intent(inout) :: OBC !< Open boundary control structure type(OBC_segment_type), pointer :: segment => NULL() + real :: I_scale ! The inverse of the scaling factor for the tracers. + ! For salinity the units would be [ppt S-1 ~> 1] integer :: i, j, k, m, n do n=1,OBC%number_of_segments @@ -2004,7 +2013,7 @@ subroutine setup_OBC_tracer_reservoirs(G, GV, OBC) if (allocated(segment%tr_Reg%Tr(m)%tres)) then do k=1,GV%ke do j=segment%HI%jsd,segment%HI%jed - OBC%tres_x(I,j,k,m) = segment%tr_Reg%Tr(m)%t(i,j,k) + OBC%tres_x(I,j,k,m) = I_scale * segment%tr_Reg%Tr(m)%t(i,j,k) enddo enddo endif @@ -2012,10 +2021,11 @@ subroutine setup_OBC_tracer_reservoirs(G, GV, OBC) else J = segment%HI%JsdB do m=1,OBC%ntr + I_scale = 1.0 ; if (segment%tr_Reg%Tr(m)%scale /= 0.0) I_scale = 1.0 / segment%tr_Reg%Tr(m)%scale if (allocated(segment%tr_Reg%Tr(m)%tres)) then do k=1,GV%ke do i=segment%HI%isd,segment%HI%ied - OBC%tres_y(i,J,k,m) = segment%tr_Reg%Tr(m)%t(i,J,k) + OBC%tres_y(i,J,k,m) = I_scale * segment%tr_Reg%Tr(m)%t(i,J,k) enddo enddo endif @@ -2125,7 +2135,7 @@ subroutine radiation_open_bdry_conds(OBC, u_new, u_old, v_new, v_old, G, GV, US, if (allocated(segment%tr_Reg%Tr(m)%tres)) then do k=1,GV%ke do j=segment%HI%jsd,segment%HI%jed - segment%tr_Reg%Tr(m)%tres(I,j,k) = OBC%tres_x(I,j,k,m) + segment%tr_Reg%Tr(m)%tres(I,j,k) = segment%tr_Reg%Tr(m)%scale * OBC%tres_x(I,j,k,m) enddo enddo endif @@ -2136,7 +2146,7 @@ subroutine radiation_open_bdry_conds(OBC, u_new, u_old, v_new, v_old, G, GV, US, if (allocated(segment%tr_Reg%Tr(m)%tres)) then do k=1,GV%ke do i=segment%HI%isd,segment%HI%ied - segment%tr_Reg%Tr(m)%tres(i,J,k) = OBC%tres_y(i,J,k,m) + segment%tr_Reg%Tr(m)%tres(i,J,k) = segment%tr_Reg%Tr(m)%scale * OBC%tres_y(i,J,k,m) enddo enddo endif @@ -3796,7 +3806,9 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time) tmp_buffer_in => tmp_buffer endif - call time_interp_external(segment%field(m)%fid,Time, tmp_buffer_in) + ! This is where the data values are actually read in. + call time_interp_external(segment%field(m)%fid, Time, tmp_buffer_in) + ! NOTE: Rotation of face-points require that we skip the final value if (turns /= 0) then ! TODO: This is hardcoded for 90 degrees, and needs to be generalized. @@ -3863,6 +3875,7 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time) ! no dz for tidal variables if (segment%field(m)%nk_src > 1 .and.& (index(segment%field(m)%name, 'phase') <= 0 .and. index(segment%field(m)%name, 'amp') <= 0)) then + ! This is where the 2-d tidal data values are actually read in. call time_interp_external(segment%field(m)%fid_dz, Time, tmp_buffer_in) tmp_buffer_in(:,:,:) = tmp_buffer_in(:,:,:) * US%m_to_Z if (turns /= 0) then @@ -4230,7 +4243,7 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time) if (trim(segment%field(m)%name) == 'TEMP') then if (allocated(segment%field(m)%buffer_dst)) then do k=1,nz ; do j=js_obc2,je_obc ; do i=is_obc2,ie_obc - segment%tr_Reg%Tr(1)%t(i,j,k) = segment%field(m)%buffer_dst(i,j,k) + segment%tr_Reg%Tr(1)%t(i,j,k) = segment%tr_Reg%Tr(1)%scale * segment%field(m)%buffer_dst(i,j,k) enddo ; enddo ; enddo if (.not. segment%tr_Reg%Tr(1)%is_initialized) then ! if the tracer reservoir has not yet been initialized, then set to external value. @@ -4245,7 +4258,7 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time) elseif (trim(segment%field(m)%name) == 'SALT') then if (allocated(segment%field(m)%buffer_dst)) then do k=1,nz ; do j=js_obc2,je_obc ; do i=is_obc2,ie_obc - segment%tr_Reg%Tr(2)%t(i,j,k) = segment%field(m)%buffer_dst(i,j,k) + segment%tr_Reg%Tr(2)%t(i,j,k) = segment%tr_Reg%Tr(2)%scale * segment%field(m)%buffer_dst(i,j,k) enddo ; enddo ; enddo if (.not. segment%tr_Reg%Tr(2)%is_initialized) then !if the tracer reservoir has not yet been initialized, then set to external value. @@ -4428,7 +4441,7 @@ end subroutine segment_tracer_registry_init !> Register a tracer array that is active on an OBC segment, potentially also specifying how the !! tracer inflow values are specified. subroutine register_segment_tracer(tr_ptr, param_file, GV, segment, & - OBC_scalar, OBC_array) + OBC_scalar, OBC_array, scale) type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure type(tracer_type), target :: tr_ptr !< A target that can be used to set a pointer to the !! stored value of tr. This target must be @@ -4440,10 +4453,13 @@ subroutine register_segment_tracer(tr_ptr, param_file, GV, segment, & type(param_file_type), intent(in) :: param_file !< file to parse for model parameter values type(OBC_segment_type), intent(inout) :: segment !< current segment data structure real, optional, intent(in) :: OBC_scalar !< If present, use scalar value for segment tracer - !! inflow concentration. + !! inflow concentration, including any rescaling to + !! put the tracer concentration into its internal units. logical, optional, intent(in) :: OBC_array !< If true, use array values for segment tracer !! inflow concentration. - + real, optional, intent(in) :: scale !< A scaling factor that should be used with any + !! data that is read in, to convert it to the internal + !! units of this tracer. ! Local variables integer :: ntseg @@ -4468,6 +4484,7 @@ subroutine register_segment_tracer(tr_ptr, param_file, GV, segment, & segment%tr_Reg%Tr(ntseg)%Tr => tr_ptr segment%tr_Reg%Tr(ntseg)%name = tr_ptr%name + segment%tr_Reg%Tr(ntseg)%scale = 1.0 ; if (present(scale)) segment%tr_Reg%Tr(ntseg)%scale = scale if (segment%tr_Reg%locked) call MOM_error(FATAL, & "MOM register_segment_tracer was called for variable "//trim(segment%tr_Reg%Tr(ntseg)%name)//& @@ -4503,8 +4520,9 @@ subroutine segment_tracer_registry_end(Reg) endif end subroutine segment_tracer_registry_end -subroutine register_temp_salt_segments(GV, OBC, tr_Reg, param_file) +subroutine register_temp_salt_segments(GV, US, OBC, tr_Reg, param_file) type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure + type(unit_scale_type), intent(in) :: US !< Unit scaling type type(ocean_OBC_type), pointer :: OBC !< Open boundary structure type(tracer_registry_type), pointer :: tr_Reg !< Tracer registry type(param_file_type), intent(in) :: param_file !< file to parse for model parameter values @@ -4527,18 +4545,19 @@ subroutine register_temp_salt_segments(GV, OBC, tr_Reg, param_file) name = 'temp' call tracer_name_lookup(tr_Reg, tr_ptr, name) call register_segment_tracer(tr_ptr, param_file, GV, segment, & - OBC_array=segment%temp_segment_data_exists) + OBC_array=segment%temp_segment_data_exists, scale=US%degC_to_C) name = 'salt' call tracer_name_lookup(tr_Reg, tr_ptr, name) call register_segment_tracer(tr_ptr, param_file, GV, segment, & - OBC_array=segment%salt_segment_data_exists) + OBC_array=segment%salt_segment_data_exists, scale=US%ppt_to_S) enddo end subroutine register_temp_salt_segments -subroutine fill_temp_salt_segments(G, GV, OBC, tv) +subroutine fill_temp_salt_segments(G, GV, US, OBC, tv) type(ocean_grid_type), intent(in) :: G !< Ocean grid structure type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure + type(unit_scale_type), intent(in) :: US !< Unit scaling type(ocean_OBC_type), pointer :: OBC !< Open boundary structure type(thermo_var_ptrs), intent(inout) :: tv !< Thermodynamics structure @@ -4960,6 +4979,8 @@ subroutine update_segment_tracer_reservoirs(G, GV, uhr, vhr, h, OBC, dt, Reg) real :: u_L_in, u_L_out ! The zonal distance moved in or out of a cell [L ~> m] real :: v_L_in, v_L_out ! The meridional distance moved in or out of a cell [L ~> m] real :: fac1 ! The denominator of the expression for tracer updates [nondim] + real :: I_scale ! The inverse of the scaling factor for the tracers. + ! For salinity the units would be [ppt S-1 ~> 1] integer :: i, j, k, m, n, ntr, nz integer :: ishift, idir, jshift, jdir @@ -4981,17 +5002,20 @@ subroutine update_segment_tracer_reservoirs(G, GV, uhr, vhr, h, OBC, dt, Reg) ! Can keep this or take it out, either way if (G%mask2dT(I+ishift,j) == 0.0) cycle ! Update the reservoir tracer concentration implicitly using a Backward-Euler timestep - do m=1,ntr ; if (allocated(segment%tr_Reg%Tr(m)%tres)) then ; do k=1,nz - u_L_out = max(0.0, (idir*uhr(I,j,k))*segment%Tr_InvLscale_out / & - ((h(i+ishift,j,k) + GV%H_subroundoff)*G%dyCu(I,j))) - u_L_in = min(0.0, (idir*uhr(I,j,k))*segment%Tr_InvLscale_in / & - ((h(i+ishift,j,k) + GV%H_subroundoff)*G%dyCu(I,j))) - fac1 = 1.0 + (u_L_out-u_L_in) - segment%tr_Reg%Tr(m)%tres(I,j,k) = (1.0/fac1)*(segment%tr_Reg%Tr(m)%tres(I,j,k) + & - (u_L_out*Reg%Tr(m)%t(I+ishift,j,k) - & - u_L_in*segment%tr_Reg%Tr(m)%t(I,j,k))) - if (allocated(OBC%tres_x)) OBC%tres_x(I,j,k,m) = segment%tr_Reg%Tr(m)%tres(I,j,k) - enddo ; endif ; enddo + do m=1,ntr + I_scale = 1.0 ; if (segment%tr_Reg%Tr(m)%scale /= 0.0) I_scale = 1.0 / segment%tr_Reg%Tr(m)%scale + if (allocated(segment%tr_Reg%Tr(m)%tres)) then ; do k=1,nz + u_L_out = max(0.0, (idir*uhr(I,j,k))*segment%Tr_InvLscale_out / & + ((h(i+ishift,j,k) + GV%H_subroundoff)*G%dyCu(I,j))) + u_L_in = min(0.0, (idir*uhr(I,j,k))*segment%Tr_InvLscale_in / & + ((h(i+ishift,j,k) + GV%H_subroundoff)*G%dyCu(I,j))) + fac1 = 1.0 + (u_L_out-u_L_in) + segment%tr_Reg%Tr(m)%tres(I,j,k) = (1.0/fac1)*(segment%tr_Reg%Tr(m)%tres(I,j,k) + & + (u_L_out*Reg%Tr(m)%t(I+ishift,j,k) - & + u_L_in*segment%tr_Reg%Tr(m)%t(I,j,k))) + if (allocated(OBC%tres_x)) OBC%tres_x(I,j,k,m) = segment%tr_Reg%Tr(m)%tres(I,j,k) + enddo ; endif + enddo enddo elseif (segment%is_N_or_S) then J = segment%HI%JsdB @@ -5006,17 +5030,20 @@ subroutine update_segment_tracer_reservoirs(G, GV, uhr, vhr, h, OBC, dt, Reg) ! Can keep this or take it out, either way if (G%mask2dT(i,j+jshift) == 0.0) cycle ! Update the reservoir tracer concentration implicitly using a Backward-Euler timestep - do m=1,ntr ; if (allocated(segment%tr_Reg%Tr(m)%tres)) then ; do k=1,nz - v_L_out = max(0.0, (jdir*vhr(i,J,k))*segment%Tr_InvLscale_out / & - ((h(i,j+jshift,k) + GV%H_subroundoff)*G%dxCv(i,J))) - v_L_in = min(0.0, (jdir*vhr(i,J,k))*segment%Tr_InvLscale_in / & - ((h(i,j+jshift,k) + GV%H_subroundoff)*G%dxCv(i,J))) - fac1 = 1.0 + (v_L_out-v_L_in) - segment%tr_Reg%Tr(m)%tres(i,J,k) = (1.0/fac1)*(segment%tr_Reg%Tr(m)%tres(i,J,k) + & - (v_L_out*Reg%Tr(m)%t(i,J+jshift,k) - & - v_L_in*segment%tr_Reg%Tr(m)%t(i,J,k))) - if (allocated(OBC%tres_y)) OBC%tres_y(i,J,k,m) = segment%tr_Reg%Tr(m)%tres(i,J,k) - enddo ; endif ; enddo + do m=1,ntr + I_scale = 1.0 ; if (segment%tr_Reg%Tr(m)%scale /= 0.0) I_scale = 1.0 / segment%tr_Reg%Tr(m)%scale + if (allocated(segment%tr_Reg%Tr(m)%tres)) then ; do k=1,nz + v_L_out = max(0.0, (jdir*vhr(i,J,k))*segment%Tr_InvLscale_out / & + ((h(i,j+jshift,k) + GV%H_subroundoff)*G%dxCv(i,J))) + v_L_in = min(0.0, (jdir*vhr(i,J,k))*segment%Tr_InvLscale_in / & + ((h(i,j+jshift,k) + GV%H_subroundoff)*G%dxCv(i,J))) + fac1 = 1.0 + (v_L_out-v_L_in) + segment%tr_Reg%Tr(m)%tres(i,J,k) = (1.0/fac1)*(segment%tr_Reg%Tr(m)%tres(i,J,k) + & + (v_L_out*Reg%Tr(m)%t(i,J+jshift,k) - & + v_L_in*segment%tr_Reg%Tr(m)%t(i,J,k))) + if (allocated(OBC%tres_y)) OBC%tres_y(i,J,k,m) = I_scale * segment%tr_Reg%Tr(m)%tres(i,J,k) + enddo ; endif + enddo enddo endif enddo ; endif ; endif @@ -5363,7 +5390,7 @@ subroutine rotate_OBC_init(OBC_in, G, GV, US, param_file, tv, restart_CS, OBC) enddo if (use_temperature) & - call fill_temp_salt_segments(G, GV, OBC, tv) + call fill_temp_salt_segments(G, GV, US, OBC, tv) call open_boundary_init(G, GV, US, param_file, OBC, restart_CS) end subroutine rotate_OBC_init diff --git a/src/core/MOM_variables.F90 b/src/core/MOM_variables.F90 index 7cdf3e8e71..b0d12018f7 100644 --- a/src/core/MOM_variables.F90 +++ b/src/core/MOM_variables.F90 @@ -37,7 +37,7 @@ module MOM_variables end type p2d !> Pointers to various fields which may be used describe the surface state of MOM, and which -!! will be returned to a the calling program +!! will be returned to the calling program type, public :: surface real, allocatable, dimension(:,:) :: & SST, & !< The sea surface temperature [degC]. @@ -81,8 +81,8 @@ module MOM_variables !! potential temperature, salinity, heat capacity, and the equation of state control structure. type, public :: thermo_var_ptrs ! If allocated, the following variables have nz layers. - real, pointer :: T(:,:,:) => NULL() !< Potential temperature [degC]. - real, pointer :: S(:,:,:) => NULL() !< Salinity [PSU] or [gSalt/kg], generically [ppt]. + real, pointer :: T(:,:,:) => NULL() !< Potential temperature [C ~> degC]. + real, pointer :: S(:,:,:) => NULL() !< Salinity [PSU] or [gSalt/kg], generically [S ~> ppt]. real, pointer :: p_surf(:,:) => NULL() !< Ocean surface pressure used in equation of state !! calculations [R L2 T-2 ~> Pa] type(EOS_type), pointer :: eqn_of_state => NULL() !< Type that indicates the @@ -90,15 +90,14 @@ module MOM_variables real :: P_Ref !< The coordinate-density reference pressure [R L2 T-2 ~> Pa]. !! This is the pressure used to calculate Rml from !! T and S when eqn_of_state is associated. - real :: C_p !< The heat capacity of seawater [Q degC-1 ~> J degC-1 kg-1]. + real :: C_p !< The heat capacity of seawater [Q C-1 ~> J degC-1 kg-1]. !! When conservative temperature is used, this is !! constant and exactly 3991.86795711963 J degC-1 kg-1. logical :: T_is_conT = .false. !< If true, the temperature variable tv%T is !! actually the conservative temperature [degC]. logical :: S_is_absS = .false. !< If true, the salinity variable tv%S is !! actually the absolute salinity in units of [gSalt kg-1]. - real :: min_salinity = 0.01 !< The minimum value of salinity when BOUND_SALINITY=True [ppt]. - !! The default is 0.01 for backward compatibility but should be 0. + real :: min_salinity !< The minimum value of salinity when BOUND_SALINITY=True [S ~> ppt]. ! These arrays are accumulated fluxes for communication with other components. real, dimension(:,:), pointer :: frazil => NULL() !< The energy needed to heat the ocean column to the @@ -111,19 +110,19 @@ module MOM_variables real, dimension(:,:), pointer :: TempxPmE => NULL() !< The net inflow of water into the ocean times the !! temperature at which this inflow occurs since the - !! last call to calculate_surface_state [degC R Z ~> degC kg m-2]. + !! last call to calculate_surface_state [C R Z ~> degC kg m-2]. !! This should be prescribed in the forcing fields, but !! as it often is not, this is a useful heat budget diagnostic. real, dimension(:,:), pointer :: internal_heat => NULL() !< Any internal or geothermal heat sources that !! have been applied to the ocean since the last call to - !! calculate_surface_state [degC R Z ~> degC kg m-2]. + !! calculate_surface_state [C R Z ~> degC kg m-2]. ! The following variables are most normally not used but when they are they ! will be either set by parameterizations or prognostic. - real, pointer :: varT(:,:,:) => NULL() !< SGS variance of potential temperature [degC2]. - real, pointer :: varS(:,:,:) => NULL() !< SGS variance of salinity [ppt2]. + real, pointer :: varT(:,:,:) => NULL() !< SGS variance of potential temperature [C2 ~> degC2]. + real, pointer :: varS(:,:,:) => NULL() !< SGS variance of salinity [S2 ~> ppt2]. real, pointer :: covarTS(:,:,:) => NULL() !< SGS covariance of salinity and potential - !! temperature [degC ppt]. + !! temperature [C S ~> degC ppt]. end type thermo_var_ptrs !> Pointers to all of the prognostic variables allocated in MOM_variables.F90 and MOM.F90. @@ -133,8 +132,8 @@ module MOM_variables !! they refer to in MOM.F90. type, public :: ocean_internal_state real, pointer, dimension(:,:,:) :: & - T => NULL(), & !< Pointer to the temperature state variable [degC] - S => NULL(), & !< Pointer to the salinity state variable [ppt ~> PSU or g/kg] + T => NULL(), & !< Pointer to the temperature state variable [C ~> degC] + S => NULL(), & !< Pointer to the salinity state variable [S ~> ppt] (i.e., PSU or g/kg) u => NULL(), & !< Pointer to the zonal velocity [L T-1 ~> m s-1] v => NULL(), & !< Pointer to the meridional velocity [L T-1 ~> m s-1] h => NULL() !< Pointer to the layer thicknesses [H ~> m or kg m-2] @@ -580,15 +579,15 @@ subroutine MOM_thermovar_chksum(mesg, tv, G, US) ! counts, there must be no redundant points, so all variables use is..ie ! and js...je as their extent. if (associated(tv%T)) & - call hchksum(tv%T, mesg//" tv%T", G%HI) + call hchksum(tv%T, mesg//" tv%T", G%HI, scale=US%C_to_degC) if (associated(tv%S)) & - call hchksum(tv%S, mesg//" tv%S", G%HI) + call hchksum(tv%S, mesg//" tv%S", G%HI, scale=US%S_to_ppt) if (associated(tv%frazil)) & call hchksum(tv%frazil, mesg//" tv%frazil", G%HI, scale=US%Q_to_J_kg*US%RZ_to_kg_m2) if (associated(tv%salt_deficit)) & - call hchksum(tv%salt_deficit, mesg//" tv%salt_deficit", G%HI, scale=US%RZ_to_kg_m2) + call hchksum(tv%salt_deficit, mesg//" tv%salt_deficit", G%HI, scale=US%RZ_to_kg_m2*US%S_to_ppt) if (associated(tv%TempxPmE)) & - call hchksum(tv%TempxPmE, mesg//" tv%TempxPmE", G%HI, scale=US%RZ_to_kg_m2) + call hchksum(tv%TempxPmE, mesg//" tv%TempxPmE", G%HI, scale=US%RZ_to_kg_m2*US%C_to_degC) end subroutine MOM_thermovar_chksum end module MOM_variables diff --git a/src/diagnostics/MOM_PointAccel.F90 b/src/diagnostics/MOM_PointAccel.F90 index e52feec697..423ef2b4f9 100644 --- a/src/diagnostics/MOM_PointAccel.F90 +++ b/src/diagnostics/MOM_PointAccel.F90 @@ -50,8 +50,8 @@ module MOM_PointAccel v_av => NULL(), & !< Time average velocity [L T-1 ~> m s-1] u_prev => NULL(), & !< Previous u-velocity [L T-1 ~> m s-1] v_prev => NULL(), & !< Previous v-velocity [L T-1 ~> m s-1] - T => NULL(), & !< Temperature [degC] - S => NULL(), & !< Salinity [ppt] + T => NULL(), & !< Temperature [C ~> degC] + S => NULL(), & !< Salinity [S ~> ppt] u_accel_bt => NULL(), & !< Barotropic u-accelerations [L T-2 ~> m s-2] v_accel_bt => NULL() !< Barotropic v-accelerations [L T-2 ~> m s-2] end type PointAccel_CS @@ -94,6 +94,8 @@ subroutine write_u_accel(I, j, um, hin, ADp, CDp, dt, G, GV, US, CS, vel_rpt, st real :: h_scale ! A scaling factor for thicknesses [m H-1 ~> 1 or m3 kg-1] real :: vel_scale ! A scaling factor for velocities [m T s-1 L-1 ~> 1] real :: uh_scale ! A scaling factor for transport per unit length [m2 T s-1 L-1 H-1 ~> 1 or m3 kg-1] + real :: temp_scale ! A scaling factor for temperatures [degC C-1 ~> 1] + real :: saln_scale ! A scaling factor for salinities [ppt S-1 ~> 1] integer :: yr, mo, day, hr, minute, sec, yearday integer :: k, ks, ke integer :: nz @@ -103,6 +105,7 @@ subroutine write_u_accel(I, j, um, hin, ADp, CDp, dt, G, GV, US, CS, vel_rpt, st Angstrom = GV%Angstrom_H + GV%H_subroundoff h_scale = GV%H_to_m ; vel_scale = US%L_T_to_m_s ; uh_scale = GV%H_to_m*US%L_T_to_m_s + temp_scale = US%C_to_degC ; saln_scale = US%S_to_ppt ! if (.not.associated(CS)) return nz = GV%ke @@ -257,15 +260,15 @@ subroutine write_u_accel(I, j, um, hin, ADp, CDp, dt, G, GV, US, CS, vel_rpt, st do K=ks+1,ke+1 ; if (do_k(k-1)) write(file,'(ES10.3," ")', advance='no') e(K) ; enddo if (associated(CS%T)) then write(file,'(/,"T-: ")', advance='no') - do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') CS%T(i,j,k) ; enddo + do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') temp_scale*CS%T(i,j,k) ; enddo write(file,'(/,"T+: ")', advance='no') - do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') CS%T(i+1,j,k) ; enddo + do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') temp_scale*CS%T(i+1,j,k) ; enddo endif if (associated(CS%S)) then write(file,'(/,"S-: ")', advance='no') - do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') CS%S(i,j,k) ; enddo + do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') saln_scale*CS%S(i,j,k) ; enddo write(file,'(/,"S+: ")', advance='no') - do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') CS%S(i+1,j,k) ; enddo + do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') saln_scale*CS%S(i+1,j,k) ; enddo endif if (prev_avail) then @@ -426,6 +429,8 @@ subroutine write_v_accel(i, J, vm, hin, ADp, CDp, dt, G, GV, US, CS, vel_rpt, st real :: h_scale ! A scaling factor for thicknesses [m H-1 ~> 1 or m3 kg-1] real :: vel_scale ! A scaling factor for velocities [m T s-1 L-1 ~> 1] real :: uh_scale ! A scaling factor for transport per unit length [m2 T s-1 L-1 H-1 ~> 1 or m3 kg-1] + real :: temp_scale ! A scaling factor for temperatures [degC C-1 ~> 1] + real :: saln_scale ! A scaling factor for salinities [ppt S-1 ~> 1] integer :: yr, mo, day, hr, minute, sec, yearday integer :: k, ks, ke integer :: nz @@ -435,6 +440,7 @@ subroutine write_v_accel(i, J, vm, hin, ADp, CDp, dt, G, GV, US, CS, vel_rpt, st Angstrom = GV%Angstrom_H + GV%H_subroundoff h_scale = GV%H_to_m ; vel_scale = US%L_T_to_m_s ; uh_scale = GV%H_to_m*US%L_T_to_m_s + temp_scale = US%C_to_degC ; saln_scale = US%S_to_ppt ! if (.not.associated(CS)) return nz = GV%ke @@ -592,15 +598,15 @@ subroutine write_v_accel(i, J, vm, hin, ADp, CDp, dt, G, GV, US, CS, vel_rpt, st do K=ks+1,ke+1 ; if (do_k(k-1)) write(file,'(ES10.3," ")', advance='no') e(K) ; enddo if (associated(CS%T)) then write(file,'(/,"T-: ")', advance='no') - do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') CS%T(i,j,k) ; enddo + do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') temp_scale*CS%T(i,j,k) ; enddo write(file,'(/,"T+: ")', advance='no') - do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') CS%T(i,j+1,k) ; enddo + do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') temp_scale*CS%T(i,j+1,k) ; enddo endif if (associated(CS%S)) then write(file,'(/,"S-: ")', advance='no') - do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') CS%S(i,j,k) ; enddo + do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') saln_scale*CS%S(i,j,k) ; enddo write(file,'(/,"S+: ")', advance='no') - do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') CS%S(i,j+1,k) ; enddo + do k=ks,ke ; if (do_k(k)) write(file,'(ES10.3," ")', advance='no') saln_scale*CS%S(i,j+1,k) ; enddo endif if (prev_avail) then diff --git a/src/diagnostics/MOM_diagnostics.F90 b/src/diagnostics/MOM_diagnostics.F90 index 6d5417e9cb..acdf02f5f6 100644 --- a/src/diagnostics/MOM_diagnostics.F90 +++ b/src/diagnostics/MOM_diagnostics.F90 @@ -209,7 +209,6 @@ subroutine calculate_diagnostic_fields(u, v, h, uh, vh, tv, ADp, CDp, p_surf, & ! tmp array for surface properties - real :: surface_field(SZI_(G),SZJ_(G)) ! The surface temperature or salinity [degC] or [ppt] real :: pressure_1d(SZI_(G)) ! Temporary array for pressure when calling EOS [R L2 T-2 ~> Pa] real :: wt, wt_p ! The fractional weights of two successive values when interpolating from ! a list [nondim], scaled so that wt + wt_p = 1. @@ -374,7 +373,7 @@ subroutine calculate_diagnostic_fields(u, v, h, uh, vh, tv, ADp, CDp, p_surf, & pressure_1d(i) = pressure_1d(i) + 0.5*(GV%H_to_RZ*GV%g_Earth)*h(i,j,k) enddo ! Store in-situ density [R ~> kg m-3] in work_3d - call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pressure_1d, rho_in_situ, & + call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pressure_1d, rho_in_situ, & tv%eqn_of_state, EOSdom) do i=is,ie ! Cell thickness = dz = dp/(g*rho) (meter); store in work_3d work_3d(i,j,k) = (GV%H_to_RZ*h(i,j,k)) / rho_in_situ(i) @@ -401,7 +400,7 @@ subroutine calculate_diagnostic_fields(u, v, h, uh, vh, tv, ADp, CDp, p_surf, & ! for some diagnostics using TEOS-10 function calls. if ((CS%id_Tpot > 0) .or. (CS%id_tob > 0)) then do k=1,nz ; do j=js,je ; do i=is,ie - work_3d(i,j,k) = gsw_pt_from_ct(tv%S(i,j,k),tv%T(i,j,k)) + work_3d(i,j,k) = US%degC_to_C*gsw_pt_from_ct(US%S_to_ppt*tv%S(i,j,k),US%C_to_degC*tv%T(i,j,k)) enddo ; enddo ; enddo if (CS%id_Tpot > 0) call post_data(CS%id_Tpot, work_3d, CS%diag) if (CS%id_tob > 0) call post_data(CS%id_tob, work_3d(:,:,nz), CS%diag, mask=G%mask2dT) @@ -418,7 +417,7 @@ subroutine calculate_diagnostic_fields(u, v, h, uh, vh, tv, ADp, CDp, p_surf, & ! for some diagnostics using TEOS-10 function calls. if ((CS%id_Sprac > 0) .or. (CS%id_sob > 0)) then do k=1,nz ; do j=js,je ; do i=is,ie - work_3d(i,j,k) = gsw_sp_from_sr(tv%S(i,j,k)) + work_3d(i,j,k) = US%ppt_to_S*gsw_sp_from_sr(US%S_to_ppt*tv%S(i,j,k)) enddo ; enddo ; enddo if (CS%id_Sprac > 0) call post_data(CS%id_Sprac, work_3d, CS%diag) if (CS%id_sob > 0) call post_data(CS%id_sob, work_3d(:,:,nz), CS%diag, mask=G%mask2dT) @@ -430,43 +429,37 @@ subroutine calculate_diagnostic_fields(u, v, h, uh, vh, tv, ADp, CDp, p_surf, & ! volume mean potential temperature if (CS%id_thetaoga>0) then - thetaoga = global_volume_mean(tv%T, h, G, GV) + thetaoga = global_volume_mean(tv%T, h, G, GV, scale=US%C_to_degC) call post_data(CS%id_thetaoga, thetaoga, CS%diag) endif ! area mean SST if (CS%id_tosga > 0) then - do j=js,je ; do i=is,ie - surface_field(i,j) = tv%T(i,j,1) - enddo ; enddo - tosga = global_area_mean(tv%T(:,:,1), G) + tosga = global_area_mean(tv%T(:,:,1), G, scale=US%C_to_degC) call post_data(CS%id_tosga, tosga, CS%diag) endif ! volume mean salinity if (CS%id_soga>0) then - soga = global_volume_mean(tv%S, h, G, GV) + soga = global_volume_mean(tv%S, h, G, GV, scale=US%S_to_ppt) call post_data(CS%id_soga, soga, CS%diag) endif ! area mean SSS if (CS%id_sosga > 0) then - do j=js,je ; do i=is,ie - surface_field(i,j) = tv%S(i,j,1) - enddo ; enddo - sosga = global_area_mean(surface_field, G) + sosga = global_area_mean(tv%S(:,:,1), G, scale=US%S_to_ppt) call post_data(CS%id_sosga, sosga, CS%diag) endif ! layer mean potential temperature if (CS%id_temp_layer_ave>0) then - temp_layer_ave = global_layer_mean(tv%T, h, G, GV) + temp_layer_ave = global_layer_mean(tv%T, h, G, GV, scale=US%C_to_degC) call post_data(CS%id_temp_layer_ave, temp_layer_ave, CS%diag) endif ! layer mean salinity if (CS%id_salt_layer_ave>0) then - salt_layer_ave = global_layer_mean(tv%S, h, G, GV) + salt_layer_ave = global_layer_mean(tv%S, h, G, GV, scale=US%S_to_ppt) call post_data(CS%id_salt_layer_ave, salt_layer_ave, CS%diag) endif @@ -481,7 +474,7 @@ subroutine calculate_diagnostic_fields(u, v, h, uh, vh, tv, ADp, CDp, p_surf, & pressure_1d(:) = tv%P_Ref !$OMP parallel do default(shared) do k=1,nz ; do j=js-1,je+1 - call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pressure_1d, Rcv(:,j,k), tv%eqn_of_state, & + call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pressure_1d, Rcv(:,j,k), tv%eqn_of_state, & EOSdom) enddo ; enddo else ! Rcv should not be used much in this case, so fill in sensible values. @@ -607,7 +600,7 @@ subroutine calculate_diagnostic_fields(u, v, h, uh, vh, tv, ADp, CDp, p_surf, & pressure_1d(:) = 0. !$OMP parallel do default(shared) do k=1,nz ; do j=js,je - call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pressure_1d, Rcv(:,j,k), & + call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pressure_1d, Rcv(:,j,k), & tv%eqn_of_state, EOSdom) enddo ; enddo if (CS%id_rhopot0 > 0) call post_data(CS%id_rhopot0, Rcv, CS%diag) @@ -616,7 +609,7 @@ subroutine calculate_diagnostic_fields(u, v, h, uh, vh, tv, ADp, CDp, p_surf, & pressure_1d(:) = 2.0e7*US%kg_m3_to_R*US%m_s_to_L_T**2 ! 2000 dbars !$OMP parallel do default(shared) do k=1,nz ; do j=js,je - call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pressure_1d, Rcv(:,j,k), & + call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pressure_1d, Rcv(:,j,k), & tv%eqn_of_state, EOSdom) enddo ; enddo if (CS%id_rhopot2 > 0) call post_data(CS%id_rhopot2, Rcv, CS%diag) @@ -627,7 +620,7 @@ subroutine calculate_diagnostic_fields(u, v, h, uh, vh, tv, ADp, CDp, p_surf, & pressure_1d(:) = 0. ! Start at p=0 Pa at surface do k=1,nz pressure_1d(:) = pressure_1d(:) + 0.5 * h(:,j,k) * (GV%H_to_RZ*GV%g_Earth) ! Pressure in middle of layer k - call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pressure_1d, Rcv(:,j,k), & + call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pressure_1d, Rcv(:,j,k), & tv%eqn_of_state, EOSdom) pressure_1d(:) = pressure_1d(:) + 0.5 * h(:,j,k) * (GV%H_to_RZ*GV%g_Earth) ! Pressure at bottom of layer k enddo @@ -1597,19 +1590,21 @@ subroutine MOM_diagnostics_init(MIS, ADp, CDp, Time, G, GV, US, param_file, diag if (use_temperature) then if (tv%T_is_conT) then CS%id_Tpot = register_diag_field('ocean_model', 'temp', diag%axesTL, & - Time, 'Potential Temperature', 'degC') + Time, 'Potential Temperature', 'degC', conversion=US%C_to_degC) endif if (tv%S_is_absS) then CS%id_Sprac = register_diag_field('ocean_model', 'salt', diag%axesTL, & - Time, 'Salinity', 'psu') + Time, 'Salinity', 'psu', conversion=US%S_to_ppt) endif CS%id_tob = register_diag_field('ocean_model','tob', diag%axesT1, Time, & long_name='Sea Water Potential Temperature at Sea Floor', & - standard_name='sea_water_potential_temperature_at_sea_floor', units='degC') + standard_name='sea_water_potential_temperature_at_sea_floor', & + units='degC', conversion=US%C_to_degC) CS%id_sob = register_diag_field('ocean_model','sob',diag%axesT1, Time, & long_name='Sea Water Salinity at Sea Floor', & - standard_name='sea_water_salinity_at_sea_floor', units='psu') + standard_name='sea_water_salinity_at_sea_floor', & + units='psu', conversion=US%S_to_ppt) CS%id_temp_layer_ave = register_diag_field('ocean_model', 'temp_layer_ave', & diag%axesZL, Time, 'Layer Average Ocean Temperature', 'degC') @@ -1670,10 +1665,10 @@ subroutine MOM_diagnostics_init(MIS, ADp, CDp, Time, G, GV, US, param_file, diag 'In situ density', 'kg m-3', conversion=US%R_to_kg_m3) CS%id_drho_dT = register_diag_field('ocean_model', 'drho_dT', diag%axesTL, Time, & 'Partial derivative of rhoinsitu with respect to temperature (alpha)', & - 'kg m-3 degC-1', conversion=US%R_to_kg_m3) + 'kg m-3 degC-1', conversion=US%R_to_kg_m3*US%degC_to_C) CS%id_drho_dS = register_diag_field('ocean_model', 'drho_dS', diag%axesTL, Time, & 'Partial derivative of rhoinsitu with respect to salinity (beta)', & - 'kg^2 g-1 m-3', conversion=US%R_to_kg_m3) + 'kg^2 g-1 m-3', conversion=US%R_to_kg_m3*US%ppt_to_S) CS%id_du_dt = register_diag_field('ocean_model', 'dudt', diag%axesCuL, Time, & 'Zonal Acceleration', 'm s-2', conversion=US%L_T2_to_m_s2) @@ -1795,13 +1790,15 @@ subroutine MOM_diagnostics_init(MIS, ADp, CDp, Time, G, GV, US, param_file, diag if (use_temperature) then CS%id_temp_int = register_diag_field('ocean_model', 'temp_int', diag%axesT1, Time, & - 'Density weighted column integrated potential temperature', 'degC kg m-2', conversion=US%RZ_to_kg_m2, & + 'Density weighted column integrated potential temperature', & + 'degC kg m-2', conversion=US%C_to_degC*US%RZ_to_kg_m2, & cmor_field_name='opottempmint', & cmor_long_name='integral_wrt_depth_of_product_of_sea_water_density_and_potential_temperature',& cmor_standard_name='Depth integrated density times potential temperature') CS%id_salt_int = register_diag_field('ocean_model', 'salt_int', diag%axesT1, Time, & - 'Density weighted column integrated salinity', 'psu kg m-2', conversion=US%RZ_to_kg_m2, & + 'Density weighted column integrated salinity', & + 'psu kg m-2', conversion=US%S_to_ppt*US%RZ_to_kg_m2, & cmor_field_name='somint', & cmor_long_name='integral_wrt_depth_of_product_of_sea_water_density_and_salinity',& cmor_standard_name='Depth integrated density times salinity') @@ -1890,7 +1887,7 @@ subroutine register_surface_diags(Time, G, US, IDs, diag, tv) IDs%id_salt_deficit = register_diag_field('ocean_model', 'salt_deficit', diag%axesT1, Time, & 'Salt source in ocean required to supply excessive ice salt fluxes', & - 'ppt kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s) + 'ppt kg m-2 s-1', conversion=US%S_to_ppt*US%RZ_T_to_kg_m2s) IDs%id_Heat_PmE = register_diag_field('ocean_model', 'Heat_PmE', diag%axesT1, Time, & 'Heat flux into ocean from mass flux into ocean', & 'W m-2', conversion=US%QRZ_T_to_W_m2) @@ -2119,7 +2116,7 @@ subroutine write_static_fields(G, GV, US, tv, diag) use_temperature = associated(tv%T) if (use_temperature) then id = register_static_field('ocean_model','C_p', diag%axesNull, & - 'heat capacity of sea water', 'J kg-1 K-1', conversion=US%Q_to_J_kg, & + 'heat capacity of sea water', 'J kg-1 K-1', conversion=US%Q_to_J_kg*US%degC_to_C, & cmor_field_name='cpocean', & cmor_standard_name='specific_heat_capacity_of_sea_water', & cmor_long_name='specific_heat_capacity_of_sea_water') diff --git a/src/diagnostics/MOM_sum_output.F90 b/src/diagnostics/MOM_sum_output.F90 index 24c1b79bd2..0a424ad000 100644 --- a/src/diagnostics/MOM_sum_output.F90 +++ b/src/diagnostics/MOM_sum_output.F90 @@ -683,7 +683,7 @@ subroutine write_energy(u, v, h, tv, day, n, G, GV, US, CS, tracer_CSp, dt_forci if (CS%use_temperature) then Temp_int(:,:) = 0.0 ; Salt_int(:,:) = 0.0 do k=1,nz ; do j=js,je ; do i=is,ie - Salt_int(i,j) = Salt_int(i,j) + tv%S(i,j,k) * & + Salt_int(i,j) = Salt_int(i,j) + US%S_to_ppt*tv%S(i,j,k) * & (h(i,j,k)*(HL2_to_kg * areaTm(i,j))) Temp_int(i,j) = Temp_int(i,j) + (US%Q_to_J_kg*tv%C_p * tv%T(i,j,k)) * & (h(i,j,k)*(HL2_to_kg * areaTm(i,j))) @@ -756,9 +756,11 @@ subroutine write_energy(u, v, h, tv, day, n, G, GV, US, CS, tracer_CSp, dt_forci mass_chg = EFP_to_real(mass_chg_EFP) if (CS%use_temperature) then - salin = Salt / mass_tot ; salin_anom = Salt_anom / mass_tot + salin = Salt / mass_tot + salin_anom = Salt_anom / mass_tot ! salin_chg = Salt_chg / mass_tot - temp = heat / (mass_tot*US%Q_to_J_kg*tv%C_p) ; temp_anom = Heat_anom / (mass_tot*US%Q_to_J_kg*tv%C_p) + temp = heat / (mass_tot*US%Q_to_J_kg*US%degC_to_C*tv%C_p) + temp_anom = Heat_anom / (mass_tot*US%Q_to_J_kg*US%degC_to_C*tv%C_p) endif En_mass = toten / mass_tot @@ -995,18 +997,18 @@ subroutine accumulate_net_input(fluxes, sfc_state, tv, dt, G, US, CS) ! smg: old code if (associated(tv%TempxPmE)) then do j=js,je ; do i=is,ie - heat_in(i,j) = heat_in(i,j) + (fluxes%C_p * QRZL2_to_J*G%areaT(i,j)) * tv%TempxPmE(i,j) + heat_in(i,j) = heat_in(i,j) + (tv%C_p * QRZL2_to_J*G%areaT(i,j)) * tv%TempxPmE(i,j) enddo ; enddo elseif (associated(fluxes%evap)) then do j=js,je ; do i=is,ie - heat_in(i,j) = heat_in(i,j) + (US%Q_to_J_kg*fluxes%C_p * sfc_state%SST(i,j)) * FW_in(i,j) + heat_in(i,j) = heat_in(i,j) + (US%Q_to_J_kg*tv%C_p * US%degC_to_C*sfc_state%SST(i,j)) * FW_in(i,j) enddo ; enddo endif ! The following heat sources may or may not be used. if (associated(tv%internal_heat)) then do j=js,je ; do i=is,ie - heat_in(i,j) = heat_in(i,j) + (fluxes%C_p * QRZL2_to_J*G%areaT(i,j)) * tv%internal_heat(i,j) + heat_in(i,j) = heat_in(i,j) + (tv%C_p * QRZL2_to_J*G%areaT(i,j)) * tv%internal_heat(i,j) enddo ; enddo endif if (associated(tv%frazil)) then ; do j=js,je ; do i=is,ie diff --git a/src/diagnostics/MOM_wave_speed.F90 b/src/diagnostics/MOM_wave_speed.F90 index a06e9768d6..36a6d51e83 100644 --- a/src/diagnostics/MOM_wave_speed.F90 +++ b/src/diagnostics/MOM_wave_speed.F90 @@ -80,11 +80,11 @@ subroutine wave_speed(h, tv, G, GV, US, cg1, CS, full_halos, use_ebt_mode, mono_ ! Local variables real, dimension(SZK_(GV)+1) :: & - dRho_dT, & ! Partial derivative of density with temperature [R degC-1 ~> kg m-3 degC-1] - dRho_dS, & ! Partial derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1] + dRho_dT, & ! Partial derivative of density with temperature [R C-1 ~> kg m-3 degC-1] + dRho_dS, & ! Partial derivative of density with salinity [R S-1 ~> kg m-3 ppt-1] pres, & ! Interface pressure [R L2 T-2 ~> Pa] - T_int, & ! Temperature interpolated to interfaces [degC] - S_int, & ! Salinity interpolated to interfaces [ppt] + T_int, & ! Temperature interpolated to interfaces [C ~> degC] + S_int, & ! Salinity interpolated to interfaces [S ~> ppt] H_top, & ! The distance of each filtered interface from the ocean surface [Z ~> m] H_bot, & ! The distance of each filtered interface from the bottom [Z ~> m] gprime ! The reduced gravity across each interface [L2 Z-1 T-2 ~> m s-2]. @@ -93,14 +93,14 @@ subroutine wave_speed(h, tv, G, GV, US, cg1, CS, full_halos, use_ebt_mode, mono_ ! the thickness of the layer below (Igl) or above (Igu) it, in [T2 L-2 ~> s2 m-2]. real, dimension(SZK_(GV),SZI_(G)) :: & Hf, & ! Layer thicknesses after very thin layers are combined [Z ~> m] - Tf, & ! Layer temperatures after very thin layers are combined [degC] - Sf, & ! Layer salinities after very thin layers are combined [ppt] + Tf, & ! Layer temperatures after very thin layers are combined [C ~> degC] + Sf, & ! Layer salinities after very thin layers are combined [S ~> ppt] Rf ! Layer densities after very thin layers are combined [R ~> kg m-3] real, dimension(SZK_(GV)) :: & - Hc, & ! A column of layer thicknesses after convective istabilities are removed [Z ~> m] - Tc, & ! A column of layer temperatures after convective istabilities are removed [degC] - Sc, & ! A column of layer salinites after convective istabilities are removed [ppt] - Rc, & ! A column of layer densities after convective istabilities are removed [R ~> kg m-3] + Hc, & ! A column of layer thicknesses after convective instabilities are removed [Z ~> m] + Tc, & ! A column of layer temperatures after convective instabilities are removed [C ~> degC] + Sc, & ! A column of layer salinities after convective instabilities are removed [S ~> ppt] + Rc, & ! A column of layer densities after convective instabilities are removed [R ~> kg m-3] Hc_H ! Hc(:) rescaled from Z to thickness units [H ~> m or kg m-2] real :: I_Htot ! The inverse of the total filtered thicknesses [Z ~> m] real :: det, ddet @@ -112,8 +112,8 @@ subroutine wave_speed(h, tv, G, GV, US, cg1, CS, full_halos, use_ebt_mode, mono_ real, dimension(SZI_(G)) :: & htot, hmin, & ! Thicknesses [Z ~> m] H_here, & ! A thickness [Z ~> m] - HxT_here, & ! A layer integrated temperature [degC Z ~> degC m] - HxS_here, & ! A layer integrated salinity [ppt Z ~> ppt m] + HxT_here, & ! A layer integrated temperature [C Z ~> degC m] + HxS_here, & ! A layer integrated salinity [S Z ~> ppt m] HxR_here ! A layer integrated density [R Z ~> kg m-2] real :: speed2_tot ! overestimate of the mode-1 speed squared [L2 T-2 ~> m2 s-2] real :: cg1_min2 ! A floor in the squared first mode speed below which 0 is returned [L2 T-2 ~> m2 s-2] @@ -203,7 +203,7 @@ subroutine wave_speed(h, tv, G, GV, US, cg1, CS, full_halos, use_ebt_mode, mono_ !$OMP better_est,cg1_min2,tol_merge,tol_solve,c2_scale) & !$OMP private(htot,hmin,kf,H_here,HxT_here,HxS_here,HxR_here, & !$OMP Hf,Tf,Sf,Rf,pres,T_int,S_int,drho_dT,drho_dS, & -!$OMP drxh_sum,kc,Hc,Hc_H,tC,sc,I_Hnew,gprime,& +!$OMP drxh_sum,kc,Hc,Hc_H,Tc,Sc,I_Hnew,gprime,& !$OMP Rc,speed2_tot,Igl,Igu,lam0,lam,lam_it,dlam, & !$OMP mode_struct,sum_hc,N2min,gp,hw, & !$OMP ms_min,ms_max,ms_sq,H_top,H_bot,I_Htot,merge, & @@ -581,7 +581,7 @@ subroutine wave_speed(h, tv, G, GV, US, cg1, CS, full_halos, use_ebt_mode, mono_ end subroutine wave_speed -!> Solve a non-symmetric tridiagonal problem with the sum of the upper and lower diagnonals minus a +!> Solve a non-symmetric tridiagonal problem with the sum of the upper and lower diagonals minus a !! scalar contribution as the leading diagonal. !! This uses the Thomas algorithm rather than the Hallberg algorithm since the matrix is not symmetric. subroutine tdma6(n, a, c, lam, y) @@ -646,26 +646,26 @@ subroutine wave_speeds(h, tv, G, GV, US, nmodes, cn, CS, full_halos) ! Local variables real, dimension(SZK_(GV)+1) :: & - dRho_dT, & ! Partial derivative of density with temperature [R degC-1 ~> kg m-3 degC-1] - dRho_dS, & ! Partial derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1] + dRho_dT, & ! Partial derivative of density with temperature [R C-1 ~> kg m-3 degC-1] + dRho_dS, & ! Partial derivative of density with salinity [R S-1 ~> kg m-3 ppt-1] pres, & ! Interface pressure [R L2 T-2 ~> Pa] - T_int, & ! Temperature interpolated to interfaces [degC] - S_int, & ! Salinity interpolated to interfaces [ppt] + T_int, & ! Temperature interpolated to interfaces [C ~> degC] + S_int, & ! Salinity interpolated to interfaces [S ~> ppt] H_top, & ! The distance of each filtered interface from the ocean surface [Z ~> m] H_bot, & ! The distance of each filtered interface from the bottom [Z ~> m] gprime ! The reduced gravity across each interface [L2 Z-1 T-2 ~> m s-2]. real, dimension(SZK_(GV),SZI_(G)) :: & Hf, & ! Layer thicknesses after very thin layers are combined [Z ~> m] - Tf, & ! Layer temperatures after very thin layers are combined [degC] - Sf, & ! Layer salinities after very thin layers are combined [ppt] + Tf, & ! Layer temperatures after very thin layers are combined [C ~> degC] + Sf, & ! Layer salinities after very thin layers are combined [S ~> ppt] Rf ! Layer densities after very thin layers are combined [R ~> kg m-3] real, dimension(SZK_(GV)) :: & Igl, Igu, & ! The inverse of the reduced gravity across an interface times ! the thickness of the layer below (Igl) or above (Igu) it, in [T2 L-2 ~> s2 m-2]. - Hc, & ! A column of layer thicknesses after convective istabilities are removed [Z ~> m] - Tc, & ! A column of layer temperatures after convective istabilities are removed [degC] - Sc, & ! A column of layer salinites after convective istabilities are removed [ppt] - Rc ! A column of layer densities after convective istabilities are removed [R ~> kg m-3] + Hc, & ! A column of layer thicknesses after convective instabilities are removed [Z ~> m] + Tc, & ! A column of layer temperatures after convective instabilities are removed [C ~> degC] + Sc, & ! A column of layer salinities after convective instabilities are removed [S ~> ppt] + Rc ! A column of layer densities after convective instabilities are removed [R ~> kg m-3] real :: I_Htot ! The inverse of the total filtered thicknesses [Z ~> m] real :: c1_thresh ! if c1 is below this value, don't bother calculating ! cn values for higher modes [L T-1 ~> m s-1] @@ -692,8 +692,8 @@ subroutine wave_speeds(h, tv, G, GV, US, nmodes, cn, CS, full_halos) real, dimension(SZI_(G)) :: & htot, hmin, & ! Thicknesses [Z ~> m] H_here, & ! A thickness [Z ~> m] - HxT_here, & ! A layer integrated temperature [degC Z ~> degC m] - HxS_here, & ! A layer integrated salinity [ppt Z ~> ppt m] + HxT_here, & ! A layer integrated temperature [C Z ~> degC m] + HxS_here, & ! A layer integrated salinity [S Z ~> ppt m] HxR_here ! A layer integrated density [R Z ~> kg m-2] real :: speed2_tot ! overestimate of the mode-1 speed squared [L2 T-2 ~> m2 s-2] real :: speed2_min ! minimum mode speed (squared) to consider in root searching [L2 T-2 ~> m2 s-2] @@ -702,7 +702,6 @@ subroutine wave_speeds(h, tv, G, GV, US, nmodes, cn, CS, full_halos) ! A factor used in setting speed2_min [nondim] real :: I_Hnew ! The inverse of a new layer thickness [Z-1 ~> m-1] real :: drxh_sum ! The sum of density differences across interfaces times thicknesses [R Z ~> kg m-2] - real, pointer, dimension(:,:,:) :: T => NULL(), S => NULL() real :: g_Rho0 ! G_Earth/Rho0 [L2 T-2 Z-1 R-1 ~> m4 s-2 kg-1]. real :: tol_Hfrac ! Layers that together are smaller than this fraction of ! the total water column can be merged for efficiency. @@ -735,7 +734,6 @@ subroutine wave_speeds(h, tv, G, GV, US, nmodes, cn, CS, full_halos) is = G%isd ; ie = G%ied ; js = G%jsd ; je = G%jed endif ; endif - S => tv%S ; T => tv%T g_Rho0 = GV%g_Earth / GV%Rho0 ! Simplifying the following could change answers at roundoff. Z_to_pres = GV%Z_to_H * (GV%H_to_RZ * GV%g_Earth) @@ -757,7 +755,7 @@ subroutine wave_speeds(h, tv, G, GV, US, nmodes, cn, CS, full_halos) cn(:,:,:) = 0.0 min_h_frac = tol_Hfrac / real(nz) - !$OMP parallel do default(private) shared(is,ie,js,je,nz,h,G,GV,US,min_h_frac,use_EOS,T,S, & + !$OMP parallel do default(private) shared(is,ie,js,je,nz,h,G,GV,US,min_h_frac,use_EOS, & !$OMP Z_to_pres,tv,cn,g_Rho0,nmodes,cg1_min2,better_est, & !$OMP c1_thresh,tol_solve,tol_merge,c2_scale) do j=js,je @@ -781,12 +779,12 @@ subroutine wave_speeds(h, tv, G, GV, US, nmodes, cn, CS, full_halos) ! Start a new layer H_here(i) = h(i,j,k)*GV%H_to_Z - HxT_here(i) = (h(i,j,k)*GV%H_to_Z)*T(i,j,k) - HxS_here(i) = (h(i,j,k)*GV%H_to_Z)*S(i,j,k) + HxT_here(i) = (h(i,j,k)*GV%H_to_Z)*tv%T(i,j,k) + HxS_here(i) = (h(i,j,k)*GV%H_to_Z)*tv%S(i,j,k) else H_here(i) = H_here(i) + h(i,j,k)*GV%H_to_Z - HxT_here(i) = HxT_here(i) + (h(i,j,k)*GV%H_to_Z)*T(i,j,k) - HxS_here(i) = HxS_here(i) + (h(i,j,k)*GV%H_to_Z)*S(i,j,k) + HxT_here(i) = HxT_here(i) + (h(i,j,k)*GV%H_to_Z)*tv%T(i,j,k) + HxS_here(i) = HxS_here(i) + (h(i,j,k)*GV%H_to_Z)*tv%S(i,j,k) endif enddo ; enddo do i=is,ie ; if (H_here(i) > 0.0) then diff --git a/src/diagnostics/MOM_wave_structure.F90 b/src/diagnostics/MOM_wave_structure.F90 index 931532983a..c6b582a72d 100644 --- a/src/diagnostics/MOM_wave_structure.F90 +++ b/src/diagnostics/MOM_wave_structure.F90 @@ -110,24 +110,24 @@ subroutine wave_structure(h, tv, G, GV, US, cn, ModeNum, freq, CS, En, full_halo !! over the entire computational domain. ! Local variables real, dimension(SZK_(GV)+1) :: & - dRho_dT, & !< Partial derivative of density with temperature [R degC-1 ~> kg m-3 degC-1] - dRho_dS, & !< Partial derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1] + dRho_dT, & !< Partial derivative of density with temperature [R C-1 ~> kg m-3 degC-1] + dRho_dS, & !< Partial derivative of density with salinity [R S-1 ~> kg m-3 ppt-1] pres, & !< Interface pressure [R L2 T-2 ~> Pa] - T_int, & !< Temperature interpolated to interfaces [degC] - S_int, & !< Salinity interpolated to interfaces [ppt] + T_int, & !< Temperature interpolated to interfaces [C ~> degC] + S_int, & !< Salinity interpolated to interfaces [S ~> ppt] gprime !< The reduced gravity across each interface [L2 Z-1 T-2 ~> m s-2]. real, dimension(SZK_(GV)) :: & Igl, Igu !< The inverse of the reduced gravity across an interface times !< the thickness of the layer below (Igl) or above (Igu) it [T2 L-2 ~> s2 m-2]. real, dimension(SZK_(GV),SZI_(G)) :: & Hf, & !< Layer thicknesses after very thin layers are combined [Z ~> m] - Tf, & !< Layer temperatures after very thin layers are combined [degC] - Sf, & !< Layer salinities after very thin layers are combined [ppt] + Tf, & !< Layer temperatures after very thin layers are combined [C ~> degC] + Sf, & !< Layer salinities after very thin layers are combined [S ~> ppt] Rf !< Layer densities after very thin layers are combined [R ~> kg m-3] real, dimension(SZK_(GV)) :: & Hc, & !< A column of layer thicknesses after convective instabilities are removed [Z ~> m] - Tc, & !< A column of layer temperatures after convective instabilities are removed [degC] - Sc, & !< A column of layer salinites after convective instabilities are removed [ppt] + Tc, & !< A column of layer temperatures after convective instabilities are removed [C ~> degC] + Sc, & !< A column of layer salinities after convective instabilities are removed [S ~> ppt] Rc !< A column of layer densities after convective instabilities are removed [R ~> kg m-3] real, dimension(SZI_(G),SZJ_(G)) :: & htot !< The vertical sum of the thicknesses [Z ~> m] @@ -137,8 +137,8 @@ subroutine wave_structure(h, tv, G, GV, US, cn, ModeNum, freq, CS, En, full_halo real, dimension(SZI_(G)) :: & hmin, & !< Thicknesses [Z ~> m] H_here, & !< A thickness [Z ~> m] - HxT_here, & !< A layer integrated temperature [degC Z ~> degC m] - HxS_here, & !< A layer integrated salinity [ppt Z ~> ppt m] + HxT_here, & !< A layer integrated temperature [C Z ~> degC m] + HxS_here, & !< A layer integrated salinity [S Z ~> ppt m] HxR_here !< A layer integrated density [R Z ~> kg m-2] real :: I_Hnew !< The inverse of a new layer thickness [Z-1 ~> m-1] real :: drxh_sum !< The sum of density diffrences across interfaces times thicknesses [R Z ~> kg m-2] diff --git a/src/equation_of_state/MOM_EOS.F90 b/src/equation_of_state/MOM_EOS.F90 index 4542c678f2..0995895569 100644 --- a/src/equation_of_state/MOM_EOS.F90 +++ b/src/equation_of_state/MOM_EOS.F90 @@ -53,6 +53,8 @@ module MOM_EOS public calculate_TFreeze public convert_temp_salt_for_TEOS10 public extract_member_EOS +public cons_temp_to_pot_temp +public abs_saln_to_prac_saln public gsw_sp_from_sr public gsw_pt_from_ct public query_compressible @@ -127,6 +129,10 @@ module MOM_EOS real :: R_to_kg_m3 = 1. !< A constant that translates the units of density to kilograms per meter cubed. real :: RL2_T2_to_Pa = 1.!< Convert pressures from R L2 T-2 to Pa. real :: L_T_to_m_s = 1. !< Convert lateral velocities from L T-1 to m s-1. + real :: degC_to_C = 1. !< A constant that translates degrees Celsius to the units of temperature. + real :: C_to_degC = 1. !< A constant that translates the units of temperature to degrees Celsius. + real :: ppt_to_S = 1. !< A constant that translates parts per thousand to the units of salinity. + real :: S_to_ppt = 1. !< A constant that translates the units of salinity to parts per thousand. ! logical :: test_EOS = .true. ! If true, test the equation of state end type EOS_type @@ -158,17 +164,17 @@ module MOM_EOS !> Calls the appropriate subroutine to calculate density of sea water for scalar inputs. !! If rho_ref is present, the anomaly with respect to rho_ref is returned. The pressure and -!! density can be rescaled with the US. If both the US and scale arguments are present the density +!! density can be rescaled with the values stored in EOS. If the scale argument is present the density !! scaling uses the product of the two scaling factors. subroutine calculate_density_scalar(T, S, pressure, rho, EOS, rho_ref, scale) - real, intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, intent(in) :: S !< Salinity [ppt] + real, intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, intent(in) :: S !< Salinity [S ~> ppt] real, intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, intent(out) :: rho !< Density (in-situ if pressure is local) [R ~> kg m-3] type(EOS_type), intent(in) :: EOS !< Equation of state structure real, optional, intent(in) :: rho_ref !< A reference density [R ~> kg m-3] real, optional, intent(in) :: scale !< A multiplicative factor by which to scale output density in - !! combination with scaling given by US [various] + !! combination with scaling stored in EOS [various] real :: Ta(1) ! An array of temperatures [degC] real :: Sa(1) ! An array of salinities [ppt] @@ -177,7 +183,7 @@ subroutine calculate_density_scalar(T, S, pressure, rho, EOS, rho_ref, scale) real :: rho_scale ! A factor to convert density from kg m-3 to the desired units [R m3 kg-1 ~> 1] pres(1) = EOS%RL2_T2_to_Pa * pressure - Ta(1) = T ; Sa(1) = S + Ta(1) = EOS%C_to_degC * T ; Sa(1) = EOS%S_to_ppt * S if (present(rho_ref)) then call calculate_density_array(Ta, Sa, pres, rho_mks, 1, 1, EOS, EOS%R_to_kg_m3*rho_ref) else @@ -198,40 +204,45 @@ end subroutine calculate_density_scalar !! If rho_ref is present, the anomaly with respect to rho_ref is returned. The !! density can be rescaled using rho_ref. subroutine calculate_stanley_density_scalar(T, S, pressure, Tvar, TScov, Svar, rho, EOS, rho_ref, scale) - real, intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, intent(in) :: S !< Salinity [ppt] - real, intent(in) :: Tvar !< Variance of potential temperature referenced to the surface [degC2] - real, intent(in) :: TScov !< Covariance of potential temperature and salinity [degC ppt] - real, intent(in) :: Svar !< Variance of salinity [ppt2] + real, intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, intent(in) :: S !< Salinity [S ~> ppt] + real, intent(in) :: Tvar !< Variance of potential temperature referenced to the surface [C2 ~> degC2] + real, intent(in) :: TScov !< Covariance of potential temperature and salinity [C S ~> degC ppt] + real, intent(in) :: Svar !< Variance of salinity [S2 ~> ppt2] real, intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, intent(out) :: rho !< Density (in-situ if pressure is local) [R ~> kg m-3] type(EOS_type), intent(in) :: EOS !< Equation of state structure real, optional, intent(in) :: rho_ref !< A reference density [R ~> kg m-3]. real, optional, intent(in) :: scale !< A multiplicative factor by which to scale output density in - !! combination with scaling given by US [various] + !! combination with scaling stored in EOS [various] ! Local variables real :: d2RdTT, d2RdST, d2RdSS, d2RdSp, d2RdTp ! Second derivatives of density wrt T,S,p - real :: p_scale ! A factor to convert pressure to units of Pa [Pa T2 R-1 L-2 ~> 1] + real :: p_scale ! A factor to convert pressure to units of Pa [Pa T2 R-1 L-2 ~> 1] + real :: T_scale ! A factor to convert temperature to units of degC [degC C-1 ~> 1] + real :: S_scale ! A factor to convert salinity to units of ppt [ppt S-1 ~> 1] call calculate_density_scalar(T, S, pressure, rho, EOS, rho_ref) p_scale = EOS%RL2_T2_to_Pa + T_scale = EOS%C_to_degC + S_scale = EOS%S_to_ppt select case (EOS%form_of_EOS) case (EOS_LINEAR) - call calculate_density_second_derivs_linear(T, S, p_scale*pressure, d2RdSS, d2RdST, & - d2RdTT, d2RdSp, d2RdTP) + call calculate_density_second_derivs_linear(T_scale*T, S_scale*S, p_scale*pressure, & + d2RdSS, d2RdST, d2RdTT, d2RdSp, d2RdTP) case (EOS_WRIGHT) - call calculate_density_second_derivs_wright(T, S, p_scale*pressure, d2RdSS, d2RdST, & - d2RdTT, d2RdSp, d2RdTP) + call calculate_density_second_derivs_wright(T_scale*T, S_scale*S, p_scale*pressure, & + d2RdSS, d2RdST, d2RdTT, d2RdSp, d2RdTP) case (EOS_TEOS10) - call calculate_density_second_derivs_teos10(T, S, p_scale*pressure, d2RdSS, d2RdST, & - d2RdTT, d2RdSp, d2RdTP) + call calculate_density_second_derivs_teos10(T_scale*T, S_scale*S, p_scale*pressure, & + d2RdSS, d2RdST, d2RdTT, d2RdSp, d2RdTP) case default call MOM_error(FATAL, "calculate_stanley_density_scalar: EOS is not valid.") end select ! Equation 25 of Stanley et al., 2020. - rho = rho + EOS%kg_m3_to_R * ( 0.5 * d2RdTT * Tvar + ( d2RdST * TScov + 0.5 * d2RdSS * Svar ) ) + rho = rho + EOS%kg_m3_to_R * ( 0.5 * (T_scale**2 * d2RdTT) * Tvar + & + ( (S_scale*T_scale * d2RdST) * TScov + 0.5 * (S_scale**2 * d2RdSS) * Svar ) ) if (present(scale)) rho = rho * scale @@ -332,8 +343,8 @@ end subroutine calculate_stanley_density_array !! potentially limiting the domain of indices that are worked on. !! If rho_ref is present, the anomaly with respect to rho_ref is returned. subroutine calculate_density_1d(T, S, pressure, rho, EOS, dom, rho_ref, scale) - real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, dimension(:), intent(in) :: S !< Salinity [ppt] + real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, dimension(:), intent(in) :: S !< Salinity [S ~> ppt] real, dimension(:), intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, dimension(:), intent(inout) :: rho !< Density (in-situ if pressure is local) [R ~> kg m-3] type(EOS_type), intent(in) :: EOS !< Equation of state structure @@ -341,11 +352,12 @@ subroutine calculate_density_1d(T, S, pressure, rho, EOS, dom, rho_ref, scale) !! into account that arrays start at 1. real, optional, intent(in) :: rho_ref !< A reference density [R ~> kg m-3] real, optional, intent(in) :: scale !< A multiplicative factor by which to scale density - !! in combination with scaling given by US [various] + !! in combination with scaling stored in EOS [various] ! Local variables real :: rho_scale ! A factor to convert density from kg m-3 to the desired units [R m3 kg-1 ~> 1] - real :: rho_reference ! rho_ref converted to [kg m-3] real, dimension(size(rho)) :: pres ! Pressure converted to [Pa] + real, dimension(size(rho)) :: Ta ! Temperature converted to [degC] + real, dimension(size(rho)) :: Sa ! Salinity converted to [ppt] integer :: i, is, ie, npts if (present(dom)) then @@ -354,16 +366,20 @@ subroutine calculate_density_1d(T, S, pressure, rho, EOS, dom, rho_ref, scale) is = 1 ; ie = size(rho) ; npts = 1 + ie - is endif - if ((EOS%RL2_T2_to_Pa == 1.0) .and. (EOS%R_to_kg_m3 == 1.0)) then + if ((EOS%RL2_T2_to_Pa == 1.0) .and. (EOS%R_to_kg_m3 == 1.0) .and. & + (EOS%C_to_degC == 1.0) .and. (EOS%S_to_ppt == 1.0)) then call calculate_density_array(T, S, pressure, rho, is, npts, EOS, rho_ref=rho_ref) - elseif (present(rho_ref)) then ! This is the same as above, but with some extra work to rescale variables. - do i=is,ie ; pres(i) = EOS%RL2_T2_to_Pa * pressure(i) ; enddo - rho_reference = EOS%R_to_kg_m3*rho_ref - call calculate_density_array(T, S, pres, rho, is, npts, EOS, rho_ref=rho_reference) - else ! There is rescaling of variables, but rho_ref is not present. Passing a 0 value of rho_ref - ! changes answers at roundoff for some equations of state, like Wright and UNESCO. - do i=is,ie ; pres(i) = EOS%RL2_T2_to_Pa * pressure(i) ; enddo - call calculate_density_array(T, S, pres, rho, is, npts, EOS) + else ! This is the same as above, but with some extra work to rescale variables. + do i=is,ie + pres(i) = EOS%RL2_T2_to_Pa * pressure(i) + Ta(i) = EOS%C_to_degC * T(i) + Sa(i) = EOS%S_to_ppt * S(i) + enddo + if (present(rho_ref)) then + call calculate_density_array(Ta, Sa, pres, rho, is, npts, EOS, rho_ref=EOS%R_to_kg_m3*rho_ref) + else + call calculate_density_array(Ta, Sa, pres, rho, is, npts, EOS) + endif endif rho_scale = EOS%kg_m3_to_R @@ -381,23 +397,29 @@ end subroutine calculate_density_1d !! in Stanley et al., 2020. !! If rho_ref is present, the anomaly with respect to rho_ref is returned. subroutine calculate_stanley_density_1d(T, S, pressure, Tvar, TScov, Svar, rho, EOS, dom, rho_ref, scale) - real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, dimension(:), intent(in) :: S !< Salinity [ppt] + real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, dimension(:), intent(in) :: S !< Salinity [S ~> ppt] real, dimension(:), intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] - real, dimension(:), intent(in) :: Tvar !< Variance of potential temperature [degC2] - real, dimension(:), intent(in) :: TScov !< Covariance of potential temperature and salinity [degC ppt] - real, dimension(:), intent(in) :: Svar !< Variance of salinity [ppt2] + real, dimension(:), intent(in) :: Tvar !< Variance of potential temperature [C2 ~> degC2] + real, dimension(:), intent(in) :: TScov !< Covariance of potential temperature and salinity [C S ~> degC ppt] + real, dimension(:), intent(in) :: Svar !< Variance of salinity [S2 ~> ppt2] real, dimension(:), intent(inout) :: rho !< Density (in-situ if pressure is local) [R ~> kg m-3] type(EOS_type), intent(in) :: EOS !< Equation of state structure integer, dimension(2), optional, intent(in) :: dom !< The domain of indices to work on, taking !! into account that arrays start at 1. real, optional, intent(in) :: rho_ref !< A reference density [R ~> kg m-3] real, optional, intent(in) :: scale !< A multiplicative factor by which to scale density - !! in combination with scaling given by US [various] + !! in combination with scaling stored in EOS [various] ! Local variables real :: rho_scale ! A factor to convert density from kg m-3 to the desired units [R m3 kg-1 ~> 1] + real :: T2_scale ! A factor to convert temperature variance to units of degC2 [degC2 C-2 ~> 1] + real :: S2_scale ! A factor to convert salinity variance to units of ppt2 [ppt2 S-2 ~> 1] + real :: TS_scale ! A factor to convert temperture-salinity covariance to units of + ! degC ppt [degC ppt C-1 S-1 ~> 1] real :: rho_reference ! rho_ref converted to [kg m-3] real, dimension(size(rho)) :: pres ! Pressure converted to [Pa] + real, dimension(size(rho)) :: Ta ! Temperature converted to [degC] + real, dimension(size(rho)) :: Sa ! Salinity converted to [ppt] real, dimension(size(T)) :: d2RdTT, d2RdST, d2RdSS, d2RdSp, d2RdTp ! Second derivatives of density wrt T,S,p integer :: i, is, ie, npts @@ -409,7 +431,12 @@ subroutine calculate_stanley_density_1d(T, S, pressure, Tvar, TScov, Svar, rho, do i=is,ie pres(i) = EOS%RL2_T2_to_Pa * pressure(i) + Ta(i) = EOS%C_to_degC * T(i) + Sa(i) = EOS%S_to_ppt * S(i) enddo + T2_scale = EOS%C_to_degC**2 + S2_scale = EOS%S_to_ppt**2 + TS_scale = EOS%C_to_degC*EOS%S_to_ppt ! Rho_ref is seems like it is always present when calculate_Stanley_density is called, so ! always set rho_reference, even though a 0 value can change answers at roundoff with @@ -418,17 +445,17 @@ subroutine calculate_stanley_density_1d(T, S, pressure, Tvar, TScov, Svar, rho, select case (EOS%form_of_EOS) case (EOS_LINEAR) - call calculate_density_linear(T, S, pres, rho, is, npts, & + call calculate_density_linear(Ta, Sa, pres, rho, is, npts, & EOS%Rho_T0_S0, EOS%dRho_dT, EOS%dRho_dS, rho_reference) - call calculate_density_second_derivs_linear(T, S, pres, d2RdSS, d2RdST, & + call calculate_density_second_derivs_linear(Ta, Sa, pres, d2RdSS, d2RdST, & d2RdTT, d2RdSp, d2RdTP, 1, npts) case (EOS_WRIGHT) - call calculate_density_wright(T, S, pres, rho, is, npts, rho_reference) - call calculate_density_second_derivs_wright(T, S, pres, d2RdSS, d2RdST, & + call calculate_density_wright(Ta, Sa, pres, rho, is, npts, rho_reference) + call calculate_density_second_derivs_wright(Ta, Sa, pres, d2RdSS, d2RdST, & d2RdTT, d2RdSp, d2RdTP, 1, npts) case (EOS_TEOS10) - call calculate_density_teos10(T, S, pres, rho, is, npts, rho_reference) - call calculate_density_second_derivs_teos10(T, S, pres, d2RdSS, d2RdST, & + call calculate_density_teos10(Ta, Sa, pres, rho, is, npts, rho_reference) + call calculate_density_second_derivs_teos10(Ta, Sa, pres, d2RdSS, d2RdST, & d2RdTT, d2RdSp, d2RdTP, 1, npts) case default call MOM_error(FATAL, "calculate_stanley_density_scalar: EOS is not valid.") @@ -436,8 +463,9 @@ subroutine calculate_stanley_density_1d(T, S, pressure, Tvar, TScov, Svar, rho, ! Equation 25 of Stanley et al., 2020. do i=is,ie - rho(i) = rho(i) & - + ( 0.5 * d2RdTT(i) * Tvar(i) + ( d2RdST(i) * TScov(i) + 0.5 * d2RdSS(i) * Svar(i) ) ) + rho(i) = rho(i) + ( 0.5 * (T2_scale * d2RdTT(i)) * Tvar(i) + & + ( (TS_scale * d2RdST(i)) * TScov(i) + & + 0.5 * (S2_scale * d2RdSS(i)) * Svar(i) ) ) enddo rho_scale = EOS%kg_m3_to_R @@ -460,7 +488,7 @@ subroutine calculate_spec_vol_array(T, S, pressure, specvol, start, npts, EOS, s type(EOS_type), intent(in) :: EOS !< Equation of state structure real, optional, intent(in) :: spv_ref !< A reference specific volume [m3 kg-1] real, optional, intent(in) :: scale !< A multiplicative factor by which to scale specific - !! volume in combination with scaling given by US [various] + !! volume in combination with scaling stored in EOS [various] real, dimension(size(specvol)) :: rho ! Density [kg m-3] integer :: j @@ -495,26 +523,27 @@ end subroutine calculate_spec_vol_array !> Calls the appropriate subroutine to calculate specific volume of sea water !! for scalar inputs. subroutine calc_spec_vol_scalar(T, S, pressure, specvol, EOS, spv_ref, scale) - real, intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, intent(in) :: S !< Salinity [ppt] + real, intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, intent(in) :: S !< Salinity [S ~> ppt] real, intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, intent(out) :: specvol !< In situ or potential specific volume [R-1 ~> m3 kg-1] !! or other units determined by the scale argument type(EOS_type), intent(in) :: EOS !< Equation of state structure real, optional, intent(in) :: spv_ref !< A reference specific volume [R-1 ~> m3 kg-1] real, optional, intent(in) :: scale !< A multiplicative factor by which to scale specific - !! volume in combination with scaling given by US [various] + !! volume in combination with scaling stored in EOS [various] - real, dimension(1) :: Ta, Sa, pres, spv ! Rescaled single element array versions of the arguments. - real :: spv_reference ! spv_ref converted to [m3 kg-1] + real, dimension(1) :: Ta ! Rescaled single element array version of temperature [degC] + real, dimension(1) :: Sa ! Rescaled single element array version of salinity [ppt] + real, dimension(1) :: pres ! Rescaled single element array version of pressure [Pa] + real, dimension(1) :: spv ! Rescaled single element array version of specific volume [m3 kg-1] real :: spv_scale ! A factor to convert specific volume from m3 kg-1 to the desired units [kg R-1 m-3 ~> 1] - pres(1) = EOS%RL2_T2_to_Pa*pressure - Ta(1) = T ; Sa(1) = S + pres(1) = EOS%RL2_T2_to_Pa * pressure + Ta(1) = EOS%C_to_degC * T ; Sa(1) = EOS%S_to_ppt * S if (present(spv_ref)) then - spv_reference = EOS%kg_m3_to_R*spv_ref - call calculate_spec_vol_array(Ta, Sa, pres, spv, 1, 1, EOS, spv_reference) + call calculate_spec_vol_array(Ta, Sa, pres, spv, 1, 1, EOS, EOS%kg_m3_to_R*spv_ref) else call calculate_spec_vol_array(Ta, Sa, pres, spv, 1, 1, EOS) endif @@ -531,8 +560,8 @@ end subroutine calc_spec_vol_scalar !> Calls the appropriate subroutine to calculate the specific volume of sea water for 1-D array !! inputs, potentially limiting the domain of indices that are worked on. subroutine calc_spec_vol_1d(T, S, pressure, specvol, EOS, dom, spv_ref, scale) - real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, dimension(:), intent(in) :: S !< Salinity [ppt] + real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, dimension(:), intent(in) :: S !< Salinity [S ~> ppt] real, dimension(:), intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, dimension(:), intent(inout) :: specvol !< In situ specific volume [R-1 ~> m3 kg-1] type(EOS_type), intent(in) :: EOS !< Equation of state structure @@ -541,11 +570,12 @@ subroutine calc_spec_vol_1d(T, S, pressure, specvol, EOS, dom, spv_ref, scale) real, optional, intent(in) :: spv_ref !< A reference specific volume [R-1 ~> m3 kg-1] real, optional, intent(in) :: scale !< A multiplicative factor by which to scale !! output specific volume in combination with - !! scaling given by US [various] + !! scaling stored in EOS [various] ! Local variables - real, dimension(size(specvol)) :: pres ! Pressure converted to [Pa] + real, dimension(size(T)) :: pres ! Pressure converted to [Pa] + real, dimension(size(T)) :: Ta ! Temperature converted to [degC] + real, dimension(size(T)) :: Sa ! Salinity converted to [ppt] real :: spv_scale ! A factor to convert specific volume from m3 kg-1 to the desired units [kg m-3 R-1 ~> 1] - real :: spv_reference ! spv_ref converted to [m3 kg-1] integer :: i, is, ie, npts if (present(dom)) then @@ -554,16 +584,22 @@ subroutine calc_spec_vol_1d(T, S, pressure, specvol, EOS, dom, spv_ref, scale) is = 1 ; ie = size(specvol) ; npts = 1 + ie - is endif - if ((EOS%RL2_T2_to_Pa == 1.0) .and. (EOS%kg_m3_to_R == 1.0)) then + if ((EOS%RL2_T2_to_Pa == 1.0) .and. (EOS%kg_m3_to_R == 1.0) .and. & + (EOS%C_to_degC == 1.0) .and. (EOS%S_to_ppt == 1.0)) then call calculate_spec_vol_array(T, S, pressure, specvol, is, npts, EOS, spv_ref) - elseif (present(spv_ref)) then ! This is the same as above, but with some extra work to rescale variables. - do i=is,ie ; pres(i) = EOS%RL2_T2_to_Pa * pressure(i) ; enddo - spv_reference = EOS%kg_m3_to_R*spv_ref - call calculate_spec_vol_array(T, S, pres, specvol, is, npts, EOS, spv_reference) - else ! There is rescaling of variables, but spv_ref is not present. Passing a 0 value of spv_ref - ! changes answers at roundoff for some equations of state, like Wright and UNESCO. - do i=is,ie ; pres(i) = EOS%RL2_T2_to_Pa * pressure(i) ; enddo - call calculate_spec_vol_array(T, S, pres, specvol, is, npts, EOS) + else ! This is the same as above, but with some extra work to rescale variables. + do i=is,ie + pres(i) = EOS%RL2_T2_to_Pa * pressure(i) + Ta(i) = EOS%C_to_degC * T(i) + Sa(i) = EOS%S_to_ppt * S(i) + enddo + if (present(spv_ref)) then + call calculate_spec_vol_array(Ta, Sa, pres, specvol, is, npts, EOS, EOS%kg_m3_to_R*spv_ref) + else + ! There is rescaling of variables, but spv_ref is not present. Passing a 0 value of spv_ref + ! changes answers at roundoff for some equations of state, like Wright and UNESCO. + call calculate_spec_vol_array(Ta, Sa, pres, specvol, is, npts, EOS) + endif endif spv_scale = EOS%R_to_kg_m3 @@ -576,32 +612,45 @@ end subroutine calc_spec_vol_1d !> Calls the appropriate subroutine to calculate the freezing point for scalar inputs. -subroutine calculate_TFreeze_scalar(S, pressure, T_fr, EOS, pres_scale) - real, intent(in) :: S !< Salinity [ppt] - real, intent(in) :: pressure !< Pressure, in [Pa] or [R L2 T-2 ~> Pa] depending on pres_scale - real, intent(out) :: T_fr !< Freezing point potential temperature referenced - !! to the surface [degC] - type(EOS_type), intent(in) :: EOS !< Equation of state structure +subroutine calculate_TFreeze_scalar(S, pressure, T_fr, EOS, pres_scale, scale_from_EOS) + real, intent(in) :: S !< Salinity, [ppt] or [Z ~> ppt] depending on scale_from_EOS + real, intent(in) :: pressure !< Pressure, in [Pa] or [R L2 T-2 ~> Pa] depending on + !! pres_scale or scale_from_EOS + real, intent(out) :: T_fr !< Freezing point potential temperature referenced to the + !! surface [degC] or [degC ~> C] depending on scale_from_EOS + type(EOS_type), intent(in) :: EOS !< Equation of state structure real, optional, intent(in) :: pres_scale !< A multiplicative factor to convert pressure - !! into Pa [Pa T2 R-1 L-2 ~> 1]. + !! into Pa [Pa T2 R-1 L-2 ~> 1]. + logical, optional, intent(in) :: scale_from_EOS !< If present true use the dimensional scaling + !! factors stored in EOS. Omission is the same .false. ! Local variables - real :: p_scale ! A factor to convert pressure to units of Pa. + real :: p_scale ! A factor to convert pressure to units of Pa [Pa T2 R-1 L-2 ~> 1] + real :: S_scale ! A factor to convert salinity to units of ppt [ppt S-1 ~> 1] - p_scale = 1.0 ; if (present(pres_scale)) p_scale = pres_scale + p_scale = 1.0 ; S_scale = 1.0 + if (present(pres_scale)) p_scale = pres_scale + if (present(scale_from_EOS)) then ; if (scale_from_EOS) then + p_scale = EOS%RL2_T2_to_Pa + S_scale = EOS%S_to_ppt + endif ; endif select case (EOS%form_of_TFreeze) case (TFREEZE_LINEAR) - call calculate_TFreeze_linear(S, p_scale*pressure, T_fr, EOS%TFr_S0_P0, & + call calculate_TFreeze_linear(S_scale*S, p_scale*pressure, T_fr, EOS%TFr_S0_P0, & EOS%dTFr_dS, EOS%dTFr_dp) case (TFREEZE_MILLERO) - call calculate_TFreeze_Millero(S, p_scale*pressure, T_fr) + call calculate_TFreeze_Millero(S_scale*S, p_scale*pressure, T_fr) case (TFREEZE_TEOS10) - call calculate_TFreeze_teos10(S, p_scale*pressure, T_fr) + call calculate_TFreeze_teos10(S_scale*S, p_scale*pressure, T_fr) case default call MOM_error(FATAL, "calculate_TFreeze_scalar: form_of_TFreeze is not valid.") end select + if (present(scale_from_EOS)) then ; if (scale_from_EOS) then + T_fr = EOS%degC_to_C * T_fr + endif ; endif + end subroutine calculate_TFreeze_scalar !> Calls the appropriate subroutine to calculate the freezing point for a 1-D array. @@ -655,16 +704,17 @@ end subroutine calculate_TFreeze_array !> Calls the appropriate subroutine to calculate the freezing point for a 1-D array, taking !! dimensionally rescaled arguments with factors stored in EOS. subroutine calculate_TFreeze_1d(S, pressure, T_fr, EOS, dom) - real, dimension(:), intent(in) :: S !< Salinity [ppt] + real, dimension(:), intent(in) :: S !< Salinity [S ~> ppt] real, dimension(:), intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, dimension(:), intent(inout) :: T_fr !< Freezing point potential temperature referenced - !! to the surface [degC] + !! to the surface [C ~> degC] type(EOS_type), intent(in) :: EOS !< Equation of state structure integer, dimension(2), optional, intent(in) :: dom !< The domain of indices to work on, taking !! into account that arrays start at 1. ! Local variables - real, dimension(size(pressure)) :: pres ! Pressure converted to [Pa] + real, dimension(size(T_fr)) :: pres ! Pressure converted to [Pa] + real, dimension(size(T_fr)) :: Sa ! Salinity converted to [ppt] integer :: i, is, ie, npts if (present(dom)) then @@ -673,7 +723,7 @@ subroutine calculate_TFreeze_1d(S, pressure, T_fr, EOS, dom) is = 1 ; ie = size(T_Fr) ; npts = 1 + ie - is endif - if (EOS%RL2_T2_to_Pa == 1.0) then + if ((EOS%RL2_T2_to_Pa == 1.0) .and. (EOS%S_to_ppt == 1.0)) then select case (EOS%form_of_TFreeze) case (TFREEZE_LINEAR) call calculate_TFreeze_linear(S, pressure, T_fr, is, npts, & @@ -686,20 +736,27 @@ subroutine calculate_TFreeze_1d(S, pressure, T_fr, EOS, dom) call MOM_error(FATAL, "calculate_TFreeze_scalar: form_of_TFreeze is not valid.") end select else - do i=is,ie ; pres(i) = EOS%RL2_T2_to_Pa * pressure(i) ; enddo + do i=is,ie + pres(i) = EOS%RL2_T2_to_Pa * pressure(i) + Sa(i) = EOS%S_to_ppt * S(i) + enddo select case (EOS%form_of_TFreeze) case (TFREEZE_LINEAR) - call calculate_TFreeze_linear(S, pres, T_fr, is, npts, & + call calculate_TFreeze_linear(Sa, pres, T_fr, is, npts, & EOS%TFr_S0_P0, EOS%dTFr_dS, EOS%dTFr_dp) case (TFREEZE_MILLERO) - call calculate_TFreeze_Millero(S, pres, T_fr, is, npts) + call calculate_TFreeze_Millero(Sa, pres, T_fr, is, npts) case (TFREEZE_TEOS10) - call calculate_TFreeze_teos10(S, pres, T_fr, is, npts) + call calculate_TFreeze_teos10(Sa, pres, T_fr, is, npts) case default call MOM_error(FATAL, "calculate_TFreeze_scalar: form_of_TFreeze is not valid.") end select endif + if (EOS%degC_to_C /= 1.0) then + do i=is,ie ; T_fr(i) = EOS%degC_to_C * T_fr(i) ; enddo + endif + end subroutine calculate_TFreeze_1d @@ -718,7 +775,7 @@ subroutine calculate_density_derivs_array(T, S, pressure, drho_dT, drho_dS, star integer, intent(in) :: npts !< The number of values to calculate type(EOS_type), intent(in) :: EOS !< Equation of state structure real, optional, intent(in) :: scale !< A multiplicative factor by which to scale density - !! in combination with scaling given by US [various] + !! in combination with scaling stored in EOS [various] ! Local variables integer :: j @@ -749,21 +806,25 @@ end subroutine calculate_density_derivs_array !> Calls the appropriate subroutine to calculate density derivatives for 1-D array inputs. subroutine calculate_density_derivs_1d(T, S, pressure, drho_dT, drho_dS, EOS, dom, scale) - real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, dimension(:), intent(in) :: S !< Salinity [ppt] + real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, dimension(:), intent(in) :: S !< Salinity [S ~> ppt] real, dimension(:), intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, dimension(:), intent(inout) :: drho_dT !< The partial derivative of density with potential - !! temperature [R degC-1 ~> kg m-3 degC-1] + !! temperature [R C-1 ~> kg m-3 degC-1] real, dimension(:), intent(inout) :: drho_dS !< The partial derivative of density with salinity - !! [R ppt-1 ~> kg m-3 ppt-1] + !! [R S-1 ~> kg m-3 ppt-1] type(EOS_type), intent(in) :: EOS !< Equation of state structure integer, dimension(2), optional, intent(in) :: dom !< The domain of indices to work on, taking !! into account that arrays start at 1. real, optional, intent(in) :: scale !< A multiplicative factor by which to scale density - !! in combination with scaling given by US [various] + !! in combination with scaling stored in EOS [various] ! Local variables real, dimension(size(drho_dT)) :: pres ! Pressure converted to [Pa] + real, dimension(size(drho_dT)) :: Ta ! Temperature converted to [degC] + real, dimension(size(drho_dT)) :: Sa ! Salinity converted to [ppt] real :: rho_scale ! A factor to convert density from kg m-3 to the desired units [R m3 kg-1 ~> 1] + real :: dRdT_scale ! A factor to convert drho_dT to the desired units [R degC m3 C-1 kg-1 ~> 1] + real :: dRdS_scale ! A factor to convert drho_dS to the desired units [R ppt m3 S-1 kg-1 ~> 1] integer :: i, is, ie, npts if (present(dom)) then @@ -772,18 +833,24 @@ subroutine calculate_density_derivs_1d(T, S, pressure, drho_dT, drho_dS, EOS, do is = 1 ; ie = size(drho_dT) ; npts = 1 + ie - is endif - if (EOS%RL2_T2_to_Pa == 1.0) then + if ((EOS%RL2_T2_to_Pa == 1.0) .and. (EOS%C_to_degC == 1.0) .and. (EOS%S_to_ppt == 1.0)) then call calculate_density_derivs_array(T, S, pressure, drho_dT, drho_dS, is, npts, EOS) else - do i=is,ie ; pres(i) = EOS%RL2_T2_to_Pa * pressure(i) ; enddo - call calculate_density_derivs_array(T, S, pres, drho_dT, drho_dS, is, npts, EOS) + do i=is,ie + pres(i) = EOS%RL2_T2_to_Pa * pressure(i) + Ta(i) = EOS%C_to_degC * T(i) + Sa(i) = EOS%S_to_ppt * S(i) + enddo + call calculate_density_derivs_array(Ta, Sa, pres, drho_dT, drho_dS, is, npts, EOS) endif rho_scale = EOS%kg_m3_to_R if (present(scale)) rho_scale = rho_scale * scale - if (rho_scale /= 1.0) then ; do i=is,ie - drho_dT(i) = rho_scale * drho_dT(i) - drho_dS(i) = rho_scale * drho_dS(i) + dRdT_scale = rho_scale * EOS%C_to_degC + dRdS_scale = rho_scale * EOS%S_to_ppt + if ((dRdT_scale /= 1.0) .or. (dRdS_scale /= 1.0)) then ; do i=is,ie + drho_dT(i) = dRdT_scale * drho_dT(i) + drho_dS(i) = dRdS_scale * drho_dS(i) enddo ; endif end subroutine calculate_density_derivs_1d @@ -792,41 +859,49 @@ end subroutine calculate_density_derivs_1d !> Calls the appropriate subroutines to calculate density derivatives by promoting a scalar !! to a one-element array subroutine calculate_density_derivs_scalar(T, S, pressure, drho_dT, drho_dS, EOS, scale) - real, intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, intent(in) :: S !< Salinity [ppt] + real, intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, intent(in) :: S !< Salinity [S ~> ppt] real, intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, intent(out) :: drho_dT !< The partial derivative of density with potential - !! temperature [R degC-1 ~> kg m-3 degC-1] or other + !! temperature [R C-1 ~> kg m-3 degC-1] or other !! units determined by the optional scale argument real, intent(out) :: drho_dS !< The partial derivative of density with salinity, - !! in [R ppt-1 ~> kg m-3 ppt-1] or other units + !! in [R S-1 ~> kg m-3 ppt-1] or other units !! determined by the optional scale argument type(EOS_type), intent(in) :: EOS !< Equation of state structure real, optional, intent(in) :: scale !< A multiplicative factor by which to scale density - !! in combination with scaling given by US [various] + !! in combination with scaling stored in EOS [various] ! Local variables real :: rho_scale ! A factor to convert density from kg m-3 to the desired units [R m3 kg-1 ~> 1] - real :: p_scale ! A factor to convert pressure to units of Pa [Pa T2 R-1 L-2 ~> 1] + real :: dRdT_scale ! A factor to convert drho_dT to the desired units [R degC m3 C-1 kg-1 ~> 1] + real :: dRdS_scale ! A factor to convert drho_dS to the desired units [R ppt m3 S-1 kg-1 ~> 1] + real :: pres ! Pressure converted to [Pa] + real :: Ta ! Temperature converted to [degC] + real :: Sa ! Salinity converted to [ppt] - p_scale = EOS%RL2_T2_to_Pa + pres = EOS%RL2_T2_to_Pa*pressure + Ta = EOS%C_to_degC * T + Sa = EOS%S_to_ppt * S select case (EOS%form_of_EOS) case (EOS_LINEAR) - call calculate_density_derivs_linear(T, S, p_scale*pressure, drho_dT, drho_dS, & + call calculate_density_derivs_linear(Ta, Sa, pres, drho_dT, drho_dS, & EOS%Rho_T0_S0, EOS%dRho_dT, EOS%dRho_dS) case (EOS_WRIGHT) - call calculate_density_derivs_wright(T, S, p_scale*pressure, drho_dT, drho_dS) + call calculate_density_derivs_wright(Ta, Sa, pres, drho_dT, drho_dS) case (EOS_TEOS10) - call calculate_density_derivs_teos10(T, S, p_scale*pressure, drho_dT, drho_dS) + call calculate_density_derivs_teos10(Ta, Sa, pres, drho_dT, drho_dS) case default call MOM_error(FATAL, "calculate_density_derivs_scalar: EOS%form_of_EOS is not valid.") end select rho_scale = EOS%kg_m3_to_R if (present(scale)) rho_scale = rho_scale * scale - if (rho_scale /= 1.0) then - drho_dT = rho_scale * drho_dT - drho_dS = rho_scale * drho_dS + dRdT_scale = rho_scale * EOS%C_to_degC + dRdS_scale = rho_scale * EOS%S_to_ppt + if ((dRdT_scale /= 1.0) .or. (dRdS_scale /= 1.0)) then + drho_dT = dRdT_scale * drho_dT + drho_dS = dRdS_scale * drho_dS endif end subroutine calculate_density_derivs_scalar @@ -834,26 +909,28 @@ end subroutine calculate_density_derivs_scalar !> Calls the appropriate subroutine to calculate density second derivatives for 1-D array inputs. subroutine calculate_density_second_derivs_1d(T, S, pressure, drho_dS_dS, drho_dS_dT, drho_dT_dT, & drho_dS_dP, drho_dT_dP, EOS, dom, scale) - real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, dimension(:), intent(in) :: S !< Salinity [ppt] + real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, dimension(:), intent(in) :: S !< Salinity [S ~> ppt] real, dimension(:), intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, dimension(:), intent(inout) :: drho_dS_dS !< Partial derivative of beta with respect to S - !! [R ppt-2 ~> kg m-3 ppt-2] + !! [R S-2 ~> kg m-3 ppt-2] real, dimension(:), intent(inout) :: drho_dS_dT !< Partial derivative of beta with respect to T - !! [R ppt-1 degC-1 ~> kg m-3 ppt-1 degC-1] + !! [R S-1 C-1 ~> kg m-3 ppt-1 degC-1] real, dimension(:), intent(inout) :: drho_dT_dT !< Partial derivative of alpha with respect to T - !! [R degC-2 ~> kg m-3 degC-2] + !! [R C-2 ~> kg m-3 degC-2] real, dimension(:), intent(inout) :: drho_dS_dP !< Partial derivative of beta with respect to pressure - !! [T2 ppt-1 L-2 ~> kg m-3 ppt-1 Pa-1] + !! [T2 S-1 L-2 ~> kg m-3 ppt-1 Pa-1] real, dimension(:), intent(inout) :: drho_dT_dP !< Partial derivative of alpha with respect to pressure - !! [T2 degC-1 L-2 ~> kg m-3 degC-1 Pa-1] + !! [T2 C-1 L-2 ~> kg m-3 degC-1 Pa-1] type(EOS_type), intent(in) :: EOS !< Equation of state structure integer, dimension(2), optional, intent(in) :: dom !< The domain of indices to work on, taking !! into account that arrays start at 1. real, optional, intent(in) :: scale !< A multiplicative factor by which to scale density - !! in combination with scaling given by US [various] + !! in combination with scaling stored in EOS [various] ! Local variables - real, dimension(size(pressure)) :: pres ! Pressure converted to [Pa] + real, dimension(size(T)) :: pres ! Pressure converted to [Pa] + real, dimension(size(T)) :: Ta ! Temperature converted to [degC] + real, dimension(size(T)) :: Sa ! Salinity converted to [ppt] real :: rho_scale ! A factor to convert density from kg m-3 to the desired units [R m3 kg-1 ~> 1] integer :: i, is, ie, npts @@ -863,7 +940,7 @@ subroutine calculate_density_second_derivs_1d(T, S, pressure, drho_dS_dS, drho_d is = 1 ; ie = size(T) ; npts = 1 + ie - is endif - if (EOS%RL2_T2_to_Pa == 1.0) then + if ((EOS%RL2_T2_to_Pa == 1.0) .and. (EOS%C_to_degC == 1.0) .and. (EOS%S_to_ppt == 1.0)) then select case (EOS%form_of_EOS) case (EOS_LINEAR) call calculate_density_second_derivs_linear(T, S, pressure, drho_dS_dS, drho_dS_dT, & @@ -878,16 +955,20 @@ subroutine calculate_density_second_derivs_1d(T, S, pressure, drho_dS_dS, drho_d call MOM_error(FATAL, "calculate_density_derivs: EOS%form_of_EOS is not valid.") end select else - do i=is,ie ; pres(i) = EOS%RL2_T2_to_Pa * pressure(i) ; enddo + do i=is,ie + pres(i) = EOS%RL2_T2_to_Pa * pressure(i) + Ta(i) = EOS%C_to_degC * T(i) + Sa(i) = EOS%S_to_ppt * S(i) + enddo select case (EOS%form_of_EOS) case (EOS_LINEAR) - call calculate_density_second_derivs_linear(T, S, pres, drho_dS_dS, drho_dS_dT, & + call calculate_density_second_derivs_linear(Ta, Sa, pres, drho_dS_dS, drho_dS_dT, & drho_dT_dT, drho_dS_dP, drho_dT_dP, is, npts) case (EOS_WRIGHT) - call calculate_density_second_derivs_wright(T, S, pres, drho_dS_dS, drho_dS_dT, & + call calculate_density_second_derivs_wright(Ta, Sa, pres, drho_dS_dS, drho_dS_dT, & drho_dT_dT, drho_dS_dP, drho_dT_dP, is, npts) case (EOS_TEOS10) - call calculate_density_second_derivs_teos10(T, S, pres, drho_dS_dS, drho_dS_dT, & + call calculate_density_second_derivs_teos10(Ta, Sa, pres, drho_dS_dS, drho_dS_dT, & drho_dT_dT, drho_dS_dP, drho_dT_dP, is, npts) case default call MOM_error(FATAL, "calculate_density_derivs: EOS%form_of_EOS is not valid.") @@ -909,42 +990,59 @@ subroutine calculate_density_second_derivs_1d(T, S, pressure, drho_dS_dS, drho_d drho_dT_dP(i) = EOS%RL2_T2_to_Pa * drho_dT_dP(i) enddo ; endif + if (EOS%C_to_degC /= 1.0) then ; do i=is,ie + drho_dS_dT(i) = EOS%C_to_degC * drho_dS_dT(i) + drho_dT_dT(i) = EOS%C_to_degC**2 * drho_dT_dT(i) + drho_dT_dP(i) = EOS%C_to_degC * drho_dT_dP(i) + enddo ; endif + + if (EOS%S_to_ppt /= 1.0) then ; do i=is,ie + drho_dS_dS(i) = EOS%S_to_ppt**2 * drho_dS_dS(i) + drho_dS_dT(i) = EOS%S_to_ppt * drho_dS_dT(i) + drho_dS_dP(i) = EOS%S_to_ppt * drho_dS_dP(i) + enddo ; endif + end subroutine calculate_density_second_derivs_1d !> Calls the appropriate subroutine to calculate density second derivatives for scalar nputs. subroutine calculate_density_second_derivs_scalar(T, S, pressure, drho_dS_dS, drho_dS_dT, drho_dT_dT, & drho_dS_dP, drho_dT_dP, EOS, scale) - real, intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, intent(in) :: S !< Salinity [ppt] + real, intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, intent(in) :: S !< Salinity [S ~> ppt] real, intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, intent(out) :: drho_dS_dS !< Partial derivative of beta with respect to S - !! [R ppt-2 ~> kg m-3 ppt-2] + !! [R S-2 ~> kg m-3 ppt-2] real, intent(out) :: drho_dS_dT !< Partial derivative of beta with respect to T - !! [R ppt-1 degC-1 ~> kg m-3 ppt-1 degC-1] + !! [R S-1 C-1 ~> kg m-3 ppt-1 degC-1] real, intent(out) :: drho_dT_dT !< Partial derivative of alpha with respect to T - !! [R degC-2 ~> kg m-3 degC-2] + !! [R C-2 ~> kg m-3 degC-2] real, intent(out) :: drho_dS_dP !< Partial derivative of beta with respect to pressure - !! [T2 ppt-1 L-2 ~> kg m-3 ppt-1 Pa-1] + !! [T2 S-1 L-2 ~> kg m-3 ppt-1 Pa-1] real, intent(out) :: drho_dT_dP !< Partial derivative of alpha with respect to pressure - !! [T2 degC-1 L-2 ~> kg m-3 degC-1 Pa-1] + !! [T2 C-1 L-2 ~> kg m-3 degC-1 Pa-1] type(EOS_type), intent(in) :: EOS !< Equation of state structure real, optional, intent(in) :: scale !< A multiplicative factor by which to scale density - !! in combination with scaling given by US [various] + !! in combination with scaling stored in EOS [various] ! Local variables real :: rho_scale ! A factor to convert density from kg m-3 to the desired units [R m3 kg-1 ~> 1] real :: p_scale ! A factor to convert pressure to units of Pa [Pa T2 R-1 L-2 ~> 1] + real :: pres ! Pressure converted to [Pa] + real :: Ta ! Temperature converted to [degC] + real :: Sa ! Salinity converted to [ppt] - p_scale = EOS%RL2_T2_to_Pa + pres = EOS%RL2_T2_to_Pa*pressure + Ta = EOS%C_to_degC * T + Sa = EOS%S_to_ppt * S select case (EOS%form_of_EOS) case (EOS_LINEAR) - call calculate_density_second_derivs_linear(T, S, p_scale*pressure, drho_dS_dS, drho_dS_dT, & + call calculate_density_second_derivs_linear(Ta, Sa, pres, drho_dS_dS, drho_dS_dT, & drho_dT_dT, drho_dS_dP, drho_dT_dP) case (EOS_WRIGHT) - call calculate_density_second_derivs_wright(T, S, p_scale*pressure, drho_dS_dS, drho_dS_dT, & + call calculate_density_second_derivs_wright(Ta, Sa, pres, drho_dS_dS, drho_dS_dT, & drho_dT_dT, drho_dS_dP, drho_dT_dP) case (EOS_TEOS10) - call calculate_density_second_derivs_teos10(T, S, p_scale*pressure, drho_dS_dS, drho_dS_dT, & + call calculate_density_second_derivs_teos10(Ta, Sa, pres, drho_dS_dS, drho_dS_dT, & drho_dT_dT, drho_dS_dP, drho_dT_dP) case default call MOM_error(FATAL, "calculate_density_derivs: EOS%form_of_EOS is not valid.") @@ -965,6 +1063,18 @@ subroutine calculate_density_second_derivs_scalar(T, S, pressure, drho_dS_dS, dr drho_dT_dP = p_scale * drho_dT_dP endif + if (EOS%C_to_degC /= 1.0) then + drho_dS_dT = EOS%C_to_degC * drho_dS_dT + drho_dT_dT = EOS%C_to_degC**2 * drho_dT_dT + drho_dT_dP = EOS%C_to_degC * drho_dT_dP + endif + + if (EOS%S_to_ppt /= 1.0) then + drho_dS_dS = EOS%S_to_ppt**2 * drho_dS_dS + drho_dS_dT = EOS%S_to_ppt * drho_dS_dT + drho_dS_dP = EOS%S_to_ppt * drho_dS_dP + endif + end subroutine calculate_density_second_derivs_scalar !> Calls the appropriate subroutine to calculate specific volume derivatives for an array. @@ -1017,22 +1127,26 @@ end subroutine calculate_spec_vol_derivs_array !> Calls the appropriate subroutine to calculate specific volume derivatives for 1-d array inputs, !! potentially limiting the domain of indices that are worked on. subroutine calc_spec_vol_derivs_1d(T, S, pressure, dSV_dT, dSV_dS, EOS, dom, scale) - real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, dimension(:), intent(in) :: S !< Salinity [ppt] + real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, dimension(:), intent(in) :: S !< Salinity [S ~> ppt] real, dimension(:), intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, dimension(:), intent(inout) :: dSV_dT !< The partial derivative of specific volume with potential - !! temperature [R-1 degC-1 ~> m3 kg-1 degC-1] + !! temperature [R-1 C-1 ~> m3 kg-1 degC-1] real, dimension(:), intent(inout) :: dSV_dS !< The partial derivative of specific volume with salinity - !! [R-1 ppt-1 ~> m3 kg-1 ppt-1] + !! [R-1 S-1 ~> m3 kg-1 ppt-1] type(EOS_type), intent(in) :: EOS !< Equation of state structure integer, dimension(2), optional, intent(in) :: dom !< The domain of indices to work on, taking !! into account that arrays start at 1. real, optional, intent(in) :: scale !< A multiplicative factor by which to scale specific - !! volume in combination with scaling given by US [various] + !! volume in combination with scaling stored in EOS [various] ! Local variables - real, dimension(size(dSV_dT)) :: press ! Pressure converted to [Pa] + real, dimension(size(T)) :: pres ! Pressure converted to [Pa] + real, dimension(size(T)) :: Ta ! Temperature converted to [degC] + real, dimension(size(T)) :: Sa ! Salinity converted to [ppt] real :: spv_scale ! A factor to convert specific volume from m3 kg-1 to the desired units [kg R-1 m-3 ~> 1] + real :: dSVdT_scale ! A factor to convert dSV_dT to the desired units [kg degC R-1 C-1 m-3 ~> 1] + real :: dSVdS_scale ! A factor to convert dSV_dS to the desired units [kg ppt R-1 S-1 m-3 ~> 1] integer :: i, is, ie, npts if (present(dom)) then @@ -1041,18 +1155,24 @@ subroutine calc_spec_vol_derivs_1d(T, S, pressure, dSV_dT, dSV_dS, EOS, dom, sca is = 1 ; ie = size(dSV_dT) ; npts = 1 + ie - is endif - if (EOS%RL2_T2_to_Pa == 1.0) then + if ((EOS%RL2_T2_to_Pa == 1.0) .and. (EOS%C_to_degC == 1.0) .and. (EOS%S_to_ppt == 1.0)) then call calculate_spec_vol_derivs_array(T, S, pressure, dSV_dT, dSV_dS, is, npts, EOS) else - do i=is,ie ; press(i) = EOS%RL2_T2_to_Pa * pressure(i) ; enddo - call calculate_spec_vol_derivs_array(T, S, press, dSV_dT, dSV_dS, is, npts, EOS) + do i=is,ie + pres(i) = EOS%RL2_T2_to_Pa * pressure(i) + Ta(i) = EOS%C_to_degC * T(i) + Sa(i) = EOS%S_to_ppt * S(i) + enddo + call calculate_spec_vol_derivs_array(Ta, Sa, pres, dSV_dT, dSV_dS, is, npts, EOS) endif spv_scale = EOS%R_to_kg_m3 if (present(scale)) spv_scale = spv_scale * scale + dSVdT_scale = spv_scale * EOS%C_to_degC + dSVdS_scale = spv_scale * EOS%S_to_ppt if (spv_scale /= 1.0) then ; do i=is,ie - dSV_dT(i) = spv_scale * dSV_dT(i) - dSV_dS(i) = spv_scale * dSV_dS(i) + dSV_dT(i) = dSVdT_scale * dSV_dT(i) + dSV_dS(i) = dSVdS_scale * dSV_dS(i) enddo ; endif end subroutine calc_spec_vol_derivs_1d @@ -1060,10 +1180,10 @@ end subroutine calc_spec_vol_derivs_1d !> Calls the appropriate subroutine to calculate the density and compressibility for 1-D array !! inputs. The inputs and outputs use dimensionally rescaled units. -subroutine calculate_compress_1d(T, S, press, rho, drho_dp, EOS, dom) - real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, dimension(:), intent(in) :: S !< Salinity [ppt] - real, dimension(:), intent(in) :: press !< Pressure [R L2 T-2 ~> Pa] +subroutine calculate_compress_1d(T, S, pressure, rho, drho_dp, EOS, dom) + real, dimension(:), intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, dimension(:), intent(in) :: S !< Salinity [S ~> ppt] + real, dimension(:), intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, dimension(:), intent(inout) :: rho !< In situ density [R ~> kg m-3] real, dimension(:), intent(inout) :: drho_dp !< The partial derivative of density with pressure !! (also the inverse of the square of sound speed) @@ -1073,7 +1193,9 @@ subroutine calculate_compress_1d(T, S, press, rho, drho_dp, EOS, dom) !! into account that arrays start at 1. ! Local variables - real, dimension(size(press)) :: pressure ! Pressure converted to [Pa] + real, dimension(size(T)) :: pres ! Pressure converted to [Pa] + real, dimension(size(T)) :: Ta ! Temperature converted to [degC] + real, dimension(size(T)) :: Sa ! Salinity converted to [ppt] integer :: i, is, ie, npts if (present(dom)) then @@ -1082,20 +1204,24 @@ subroutine calculate_compress_1d(T, S, press, rho, drho_dp, EOS, dom) is = 1 ; ie = size(rho) ; npts = 1 + ie - is endif - do i=is,ie ; pressure(i) = EOS%RL2_T2_to_Pa * press(i) ; enddo + do i=is,ie + pres(i) = EOS%RL2_T2_to_Pa * pressure(i) + Ta(i) = EOS%C_to_degC * T(i) + Sa(i) = EOS%S_to_ppt * S(i) + enddo select case (EOS%form_of_EOS) case (EOS_LINEAR) - call calculate_compress_linear(T, S, pressure, rho, drho_dp, is, npts, & + call calculate_compress_linear(Ta, Sa, pres, rho, drho_dp, is, npts, & EOS%Rho_T0_S0, EOS%dRho_dT, EOS%dRho_dS) case (EOS_UNESCO) - call calculate_compress_unesco(T, S, pressure, rho, drho_dp, is, npts) + call calculate_compress_unesco(Ta, Sa, pres, rho, drho_dp, is, npts) case (EOS_WRIGHT) - call calculate_compress_wright(T, S, pressure, rho, drho_dp, is, npts) + call calculate_compress_wright(Ta, Sa, pres, rho, drho_dp, is, npts) case (EOS_TEOS10) - call calculate_compress_teos10(T, S, pressure, rho, drho_dp, is, npts) + call calculate_compress_teos10(Ta, Sa, pres, rho, drho_dp, is, npts) case (EOS_NEMO) - call calculate_compress_nemo(T, S, pressure, rho, drho_dp, is, npts) + call calculate_compress_nemo(Ta, Sa, pres, rho, drho_dp, is, npts) case default call MOM_error(FATAL, "calculate_compress: EOS%form_of_EOS is not valid.") end select @@ -1113,8 +1239,8 @@ end subroutine calculate_compress_1d !! with a singleton dimension and calls calculate_compress_1d. The inputs and outputs use !! dimensionally rescaled units. subroutine calculate_compress_scalar(T, S, pressure, rho, drho_dp, EOS) - real, intent(in) :: T !< Potential temperature referenced to the surface [degC] - real, intent(in) :: S !< Salinity [ppt] + real, intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] + real, intent(in) :: S !< Salinity [S ~> ppt] real, intent(in) :: pressure !< Pressure [R L2 T-2 ~> Pa] real, intent(out) :: rho !< In situ density [R ~> kg m-3] real, intent(out) :: drho_dp !< The partial derivative of density with pressure (also the @@ -1122,9 +1248,10 @@ subroutine calculate_compress_scalar(T, S, pressure, rho, drho_dp, EOS) type(EOS_type), intent(in) :: EOS !< Equation of state structure ! Local variables + ! These arrays use the same units as their counterparts in calcluate_compress_1d. real, dimension(1) :: Ta, Sa, pa, rhoa, drho_dpa - Ta(1) = T ; Sa(1) = S; pa(1) = pressure + Ta(1) = T ; Sa(1) = S ; pa(1) = pressure call calculate_compress_1d(Ta, Sa, pa, rhoa, drho_dpa, EOS) rho = rhoa(1) ; drho_dp = drho_dpa(1) @@ -1150,7 +1277,6 @@ function EOS_domain(HI, halo) result(EOSdom) end function EOS_domain - !> Calls the appropriate subroutine to calculate analytical and nearly-analytical !! integrals in pressure across layers of geopotential anomalies, which are !! required for calculating the finite-volume form pressure accelerations in a @@ -1162,9 +1288,9 @@ subroutine analytic_int_specific_vol_dp(T, S, p_t, p_b, alpha_ref, HI, EOS, & bathyP, dP_tiny, useMassWghtInterp) type(hor_index_type), intent(in) :: HI !< The horizontal index structure real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & - intent(in) :: T !< Potential temperature referenced to the surface [degC] + intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & - intent(in) :: S !< Salinity [ppt] + intent(in) :: S !< Salinity [S ~> ppt] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(in) :: p_t !< Pressure at the top of the layer [R L2 T-2 ~> Pa] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & @@ -1197,20 +1323,29 @@ subroutine analytic_int_specific_vol_dp(T, S, p_t, p_b, alpha_ref, HI, EOS, & logical, optional, intent(in) :: useMassWghtInterp !< If true, uses mass weighting !! to interpolate T/S for top and bottom integrals. + ! Local variables + real :: dRdT_scale ! A factor to convert drho_dT to the desired units [R degC m3 C-1 kg-1 ~> 1] + real :: dRdS_scale ! A factor to convert drho_dS to the desired units [R ppt m3 S-1 kg-1 ~> 1] + + + ! We should never reach this point with quadrature. EOS_quadrature indicates that numerical ! integration be used instead of analytic. This is a safety check. if (EOS%EOS_quadrature) call MOM_error(FATAL, "EOS_quadrature is set!") select case (EOS%form_of_EOS) case (EOS_LINEAR) + dRdT_scale = EOS%kg_m3_to_R * EOS%C_to_degC + dRdS_scale = EOS%kg_m3_to_R * EOS%S_to_ppt call int_spec_vol_dp_linear(T, S, p_t, p_b, alpha_ref, HI, EOS%kg_m3_to_R*EOS%Rho_T0_S0, & - EOS%kg_m3_to_R*EOS%dRho_dT, EOS%kg_m3_to_R*EOS%dRho_dS, dza, & + dRdT_scale*EOS%dRho_dT, dRdS_scale*EOS%dRho_dS, dza, & intp_dza, intx_dza, inty_dza, halo_size, & bathyP, dP_tiny, useMassWghtInterp) case (EOS_WRIGHT) call int_spec_vol_dp_wright(T, S, p_t, p_b, alpha_ref, HI, dza, intp_dza, intx_dza, & inty_dza, halo_size, bathyP, dP_tiny, useMassWghtInterp, & - SV_scale=EOS%R_to_kg_m3, pres_scale=EOS%RL2_T2_to_Pa) + SV_scale=EOS%R_to_kg_m3, pres_scale=EOS%RL2_T2_to_Pa, & + temp_scale=EOS%C_to_degC, saln_scale=EOS%S_to_ppt) case default call MOM_error(FATAL, "No analytic integration option is available with this EOS!") end select @@ -1224,9 +1359,9 @@ subroutine analytic_int_density_dz(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, EOS, intz_dpa, intx_dpa, inty_dpa, bathyT, dz_neglect, useMassWghtInterp, Z_0p) type(hor_index_type), intent(in) :: HI !< Ocean horizontal index structure real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & - intent(in) :: T !< Potential temperature referenced to the surface [degC] + intent(in) :: T !< Potential temperature referenced to the surface [C ~> degC] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & - intent(in) :: S !< Salinity [ppt] + intent(in) :: S !< Salinity [S ~> ppt] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(in) :: z_t !< Height at the top of the layer in depth units [Z ~> m] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & @@ -1265,6 +1400,8 @@ subroutine analytic_int_density_dz(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, EOS, ! Local variables real :: rho_scale ! A multiplicative factor by which to scale density from kg m-3 to the ! desired units [R m3 kg-1 ~> 1] + real :: dRdT_scale ! A factor to convert drho_dT to the desired units [R degC m3 C-1 kg-1 ~> 1] + real :: dRdS_scale ! A factor to convert drho_dS to the desired units [R ppt m3 S-1 kg-1 ~> 1] real :: pres_scale ! A multiplicative factor to convert pressure into Pa [Pa T2 R-1 L-2 ~> 1] ! We should never reach this point with quadrature. EOS_quadrature indicates that numerical @@ -1274,9 +1411,11 @@ subroutine analytic_int_density_dz(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, EOS, select case (EOS%form_of_EOS) case (EOS_LINEAR) rho_scale = EOS%kg_m3_to_R - if (rho_scale /= 1.0) then + dRdT_scale = EOS%kg_m3_to_R * EOS%C_to_degC + dRdS_scale = EOS%kg_m3_to_R * EOS%S_to_ppt + if ((rho_scale /= 1.0) .or. (dRdT_scale /= 1.0) .or. (dRdS_scale /= 1.0)) then call int_density_dz_linear(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, & - rho_scale*EOS%Rho_T0_S0, rho_scale*EOS%dRho_dT, rho_scale*EOS%dRho_dS, & + rho_scale*EOS%Rho_T0_S0, dRdT_scale*EOS%dRho_dT, dRdS_scale*EOS%dRho_dS, & dpa, intz_dpa, intx_dpa, inty_dpa, bathyT, dz_neglect, useMassWghtInterp) else call int_density_dz_linear(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, & @@ -1286,10 +1425,11 @@ subroutine analytic_int_density_dz(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, EOS, case (EOS_WRIGHT) rho_scale = EOS%kg_m3_to_R pres_scale = EOS%RL2_T2_to_Pa - if ((rho_scale /= 1.0) .or. (pres_scale /= 1.0)) then + if ((rho_scale /= 1.0) .or. (pres_scale /= 1.0) .or. (EOS%C_to_degC /= 1.0) .or. (EOS%S_to_ppt /= 1.0)) then call int_density_dz_wright(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, & dpa, intz_dpa, intx_dpa, inty_dpa, bathyT, & - dz_neglect, useMassWghtInterp, rho_scale, pres_scale, Z_0p=Z_0p) + dz_neglect, useMassWghtInterp, rho_scale, pres_scale, & + temp_scale=EOS%C_to_degC, saln_scale=EOS%S_to_ppt, Z_0p=Z_0p) else call int_density_dz_wright(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, & dpa, intz_dpa, intx_dpa, inty_dpa, bathyT, & @@ -1308,14 +1448,15 @@ logical function query_compressible(EOS) query_compressible = EOS%compressible end function query_compressible -!> Initializes EOS_type by allocating and reading parameters +!> Initializes EOS_type by allocating and reading parameters. The scaling factors in +!! US are stored in EOS for later use. subroutine EOS_init(param_file, EOS, US) type(param_file_type), intent(in) :: param_file !< Parameter file structure type(EOS_type), intent(inout) :: EOS !< Equation of state structure type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type optional :: US ! Local variables -#include "version_variable.h" +# include "version_variable.h" character(len=40) :: mdl = "MOM_EOS" ! This module's name. character(len=40) :: tmpstr @@ -1411,6 +1552,10 @@ subroutine EOS_init(param_file, EOS, US) EOS%R_to_kg_m3 = 1. ; if (present(US)) EOS%R_to_kg_m3 = US%R_to_kg_m3 EOS%RL2_T2_to_Pa = 1. ; if (present(US)) EOS%RL2_T2_to_Pa = US%RL2_T2_to_Pa EOS%L_T_to_m_s = 1. ; if (present(US)) EOS%L_T_to_m_s = US%L_T_to_m_s + EOS%degC_to_C = 1. ; if (present(US)) EOS%degC_to_C = US%degC_to_C + EOS%C_to_degC = 1. ; if (present(US)) EOS%C_to_degC = US%C_to_degC + EOS%ppt_to_S = 1. ; if (present(US)) EOS%ppt_to_S = US%ppt_to_S + EOS%S_to_ppt = 1. ; if (present(US)) EOS%S_to_ppt = US%S_to_ppt end subroutine EOS_init @@ -1477,9 +1622,9 @@ subroutine convert_temp_salt_for_TEOS10(T, S, HI, kd, mask_z, EOS) integer, intent(in) :: kd !< The number of layers to work on type(hor_index_type), intent(in) :: HI !< The horizontal index structure real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed,kd), & - intent(inout) :: T !< Potential temperature referenced to the surface [degC] + intent(inout) :: T !< Potential temperature referenced to the surface [C ~> degC] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed,kd), & - intent(inout) :: S !< Salinity [ppt] + intent(inout) :: S !< Salinity [S ~> ppt] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed,kd), & intent(in) :: mask_z !< 3d mask regulating which points to convert. type(EOS_type), intent(in) :: EOS !< Equation of state structure @@ -1491,16 +1636,105 @@ subroutine convert_temp_salt_for_TEOS10(T, S, HI, kd, mask_z, EOS) do k=1,kd ; do j=HI%jsc,HI%jec ; do i=HI%isc,HI%iec if (mask_z(i,j,k) >= 1.0) then - S(i,j,k) = gsw_sr_from_sp(S(i,j,k)) + S(i,j,k) = EOS%ppt_to_S*gsw_sr_from_sp(EOS%S_to_ppt*S(i,j,k)) ! Get absolute salinity from practical salinity, converting pressures from Pascal to dbar. ! If this option is activated, pressure will need to be added as an argument, and it should be ! moved out into module that is not shared between components, where the ocean_grid can be used. ! S(i,j,k) = gsw_sa_from_sp(S(i,j,k),pres(i,j,k)*1.0e-4,G%geoLonT(i,j),G%geoLatT(i,j)) - T(i,j,k) = gsw_ct_from_pt(S(i,j,k), T(i,j,k)) + T(i,j,k) = EOS%degC_to_C*gsw_ct_from_pt(EOS%S_to_ppt*S(i,j,k), EOS%S_to_ppt*T(i,j,k)) endif enddo ; enddo ; enddo end subroutine convert_temp_salt_for_TEOS10 + +!> Converts an array of conservative temperatures to potential temperatures. The input arguments +!! use the dimesionally rescaling as specified within the EOS type. The output potential +!! temperature uses this same scaling, but this can be replaced by the factor given by scale. +subroutine cons_temp_to_pot_temp(T, S, poTemp, EOS, dom, scale) + real, dimension(:), intent(in) :: T !< Conservative temperature [C ~> degC] + real, dimension(:), intent(in) :: S !< Absolute salinity [S ~> ppt] + real, dimension(:), intent(inout) :: poTemp !< The potential temperature with a reference pressure + !! of 0 Pa, [C ~> degC] + type(EOS_type), intent(in) :: EOS !< Equation of state structure + integer, dimension(2), optional, intent(in) :: dom !< The domain of indices to work on, taking + !! into account that arrays start at 1. + real, optional, intent(in) :: scale !< A multiplicative factor by which to scale the output + !! potential temperature in place of with scaling stored + !! in EOS. A value of 1.0 returns temperatures in [degC], + !! while the default is equivalent to EOS%degC_to_C. + + ! Local variables + real, dimension(size(T)) :: Ta ! Temperature converted to [degC] + real, dimension(size(S)) :: Sa ! Salinity converted to [ppt] + real :: T_scale ! A factor to convert potential temperature from degC to the desired units [C degC-1 ~> 1] + integer :: i, is, ie + + if (present(dom)) then + is = dom(1) ; ie = dom(2) + else + is = 1 ; ie = size(T) + endif + + if ((EOS%C_to_degC == 1.0) .and. (EOS%S_to_ppt == 1.0)) then + poTemp(is:ie) = gsw_pt_from_ct(S(is:ie), T(is:ie)) + else + do i=is,ie + Ta(i) = EOS%C_to_degC * T(i) + Sa(i) = EOS%S_to_ppt * S(i) + enddo + poTemp(is:ie) = gsw_pt_from_ct(Sa(is:ie), Ta(is:ie)) + endif + + T_scale = EOS%degC_to_C + if (present(scale)) T_scale = scale + if (T_scale /= 1.0) then ; do i=is,ie + poTemp(i) = T_scale * poTemp(i) + enddo ; endif + +end subroutine cons_temp_to_pot_temp + + +!> Converts an array of absolute salinity to practical salinity. The input arguments +!! use the dimesionally rescaling as specified within the EOS type. The output potential +!! temperature uses this same scaling, but this can be replaced by the factor given by scale. +subroutine abs_saln_to_prac_saln(S, prSaln, EOS, dom, scale) + real, dimension(:), intent(in) :: S !< Absolute salinity [S ~> ppt] + real, dimension(:), intent(inout) :: prSaln !< Practical salinity [S ~> ppt] + type(EOS_type), intent(in) :: EOS !< Equation of state structure + integer, dimension(2), optional, intent(in) :: dom !< The domain of indices to work on, taking + !! into account that arrays start at 1. + real, optional, intent(in) :: scale !< A multiplicative factor by which to scale the output + !! practical in place of with scaling stored + !! in EOS. A value of 1.0 returns salinities in [PSU], + !! while the default is equivalent to EOS%ppt_to_S. + + ! Local variables + real, dimension(size(S)) :: Sa ! Salinity converted to [ppt] + real :: S_scale ! A factor to convert practical salnity from ppt to the desired units [S ppt-1 ~> 1] + integer :: i, is, ie + + if (present(dom)) then + is = dom(1) ; ie = dom(2) + else + is = 1 ; ie = size(S) + endif + + if ((EOS%C_to_degC == 1.0) .and. (EOS%S_to_ppt == 1.0)) then + prSaln(is:ie) = gsw_sp_from_sr(Sa(is:ie)) + else + do i=is,ie ; Sa(i) = EOS%S_to_ppt * S(i) ; enddo + prSaln(is:ie) = gsw_sp_from_sr(Sa(is:ie)) + endif + + S_scale = EOS%ppt_to_S + if (present(scale)) S_scale = scale + if (S_scale /= 1.0) then ; do i=is,ie + prSaln(i) = S_scale * prSaln(i) + enddo ; endif + +end subroutine abs_saln_to_prac_saln + + !> Return value of EOS_quadrature logical function EOS_quadrature(EOS) type(EOS_type), intent(in) :: EOS !< Equation of state structure diff --git a/src/equation_of_state/MOM_EOS_Wright.F90 b/src/equation_of_state/MOM_EOS_Wright.F90 index 4b22a112db..c2e50287b2 100644 --- a/src/equation_of_state/MOM_EOS_Wright.F90 +++ b/src/equation_of_state/MOM_EOS_Wright.F90 @@ -407,14 +407,14 @@ end subroutine calculate_compress_wright !! pressure anomalies across layers, which are required for calculating the !! finite-volume form pressure accelerations in a Boussinesq model. subroutine int_density_dz_wright(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, & - dpa, intz_dpa, intx_dpa, inty_dpa, & - bathyT, dz_neglect, useMassWghtInterp, rho_scale, pres_scale, Z_0p) + dpa, intz_dpa, intx_dpa, inty_dpa, bathyT, dz_neglect, & + useMassWghtInterp, rho_scale, pres_scale, temp_scale, saln_scale, Z_0p) type(hor_index_type), intent(in) :: HI !< The horizontal index type for the arrays. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(in) :: T !< Potential temperature relative to the surface - !! [degC]. + !! [C ~> degC]. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & - intent(in) :: S !< Salinity [PSU]. + intent(in) :: S !< Salinity [S ~> PSU]. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(in) :: z_t !< Height at the top of the layer in depth units [Z ~> m]. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & @@ -451,19 +451,29 @@ subroutine int_density_dz_wright(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, & !! from kg m-3 to the desired units [R m3 kg-1 ~> 1] real, optional, intent(in) :: pres_scale !< A multiplicative factor to convert pressure !! into Pa [Pa T2 R-1 L-2 ~> 1]. + real, optional, intent(in) :: temp_scale !< A multiplicative factor by which to scale + !! temperature into degC [degC C-1 ~> 1] + real, optional, intent(in) :: saln_scale !< A multiplicative factor to convert pressure + !! into ppt [ppt S-1 ~> 1]. real, optional, intent(in) :: Z_0p !< The height at which the pressure is 0 [Z ~> m] ! Local variables - real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed) :: al0_2d, p0_2d, lambda_2d - real :: al0, p0, lambda + real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed) :: al0_2d ! A term in the Wright EOS [m3 kg-1] + real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed) :: p0_2d ! A term in the Wright EOS [Pa] + real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed) :: lambda_2d ! A term in the Wright EOS [m2 s-2] + real :: al0 ! A term in the Wright EOS [m3 kg-1] + real :: p0 ! A term in the Wright EOS [Pa] + real :: lambda ! A term in the Wright EOS [m2 s-2] real :: rho_anom ! The density anomaly from rho_ref [kg m-3]. - real :: eps, eps2, rem + real :: eps, eps2 ! A nondimensional ratio and its square [nondim] + real :: rem ! [kg m-1 s-2] real :: GxRho ! The gravitational acceleration times density and unit conversion factors [Pa Z-1 ~> kg m-2 s-2] real :: g_Earth ! The gravitational acceleration [m2 Z-1 s-2 ~> m s-2] real :: I_Rho ! The inverse of the Boussinesq density [m3 kg-1] - real :: rho_ref_mks ! The reference density in MKS units, never rescaled from kg m-3 [kg m-3] + real :: rho_ref_mks ! The reference density in MKS units [kg m-3] real :: p_ave ! The layer averaged pressure [Pa] - real :: I_al0, I_Lzz + real :: I_al0 ! The inverse of al0 [kg m-3] + real :: I_Lzz ! The inverse of the denominator [Pa-1] real :: dz ! The layer thickness [Z ~> m]. real :: hWght ! A pressure-thickness below topography [Z ~> m]. real :: hL, hR ! Pressure-thicknesses of the columns to the left and right [Z ~> m]. @@ -477,6 +487,18 @@ subroutine int_density_dz_wright(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, & real :: Pa_to_RL2_T2 ! A conversion factor of pressures from Pa to the output units indicated by ! pres_scale [R L2 T-2 Pa-1 ~> 1]. real :: z0pres ! The height at which the pressure is zero [Z ~> m] + real :: a1s ! Partly rescaled version of a1 [m3 kg-1 C-1 ~> m3 kg-1 degC-1] + real :: a2s ! Partly rescaled version of a2 [m3 kg-1 S-1 ~> m3 kg-1 ppt-1] + real :: b1s ! Partly rescaled version of b1 [Pa C-1 ~> Pa degC-1] + real :: b2s ! Partly rescaled version of b2 [Pa C-2 ~> Pa degC-2] + real :: b3s ! Partly rescaled version of b3 [Pa C-3 ~> Pa degC-3] + real :: b4s ! Partly rescaled version of b4 [Pa S-1 ~> Pa ppt-1] + real :: b5s ! Partly rescaled version of b5 [Pa C-1 S-1 ~> Pa degC-1 ppt-1] + real :: c1s ! Partly rescaled version of c1 [m2 s-2 C-1 ~> m2 s-2 degC-1] + real :: c2s ! Partly rescaled version of c2 [m2 s-2 C-2 ~> m2 s-2 degC-2] + real :: c3s ! Partly rescaled version of c3 [m2 s-2 C-3 ~> m2 s-2 degC-3] + real :: c4s ! Partly rescaled version of c4 [m2 s-2 S-1 ~> m2 s-2 ppt-1] + real :: c5s ! Partly rescaled version of c5 [m2 s-2 C-1 S-1 ~> m2 s-2 degC-1 ppt-1] logical :: do_massWeight ! Indicates whether to do mass weighting. real, parameter :: C1_3 = 1.0/3.0, C1_7 = 1.0/7.0 ! Rational constants. real, parameter :: C1_9 = 1.0/9.0, C1_90 = 1.0/90.0 ! Rational constants. @@ -504,6 +526,24 @@ subroutine int_density_dz_wright(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, & endif z0pres = 0.0 ; if (present(Z_0p)) z0pres = Z_0p + a1s = a1 ; a2s = a2 + b1s = b1 ; b2s = b2 ; b3s = b3 ; b4s = b4 ; b5s = b5 + c1s = c1 ; c2s = c2 ; c3s = c3 ; c4s = c4 ; c5s = c5 + + if (present(temp_scale)) then ; if (temp_scale /= 1.0) then + a1s = a1s * temp_scale + b1s = b1s * temp_scale ; b2s = b2s * temp_scale**2 + b3s = b3s * temp_scale**3 ; b5s = b5s * temp_scale + c1s = c1s * temp_scale ; c2s = c2s * temp_scale**2 + c3s = c3s * temp_scale**3 ; c5s = c5s * temp_scale + endif ; endif + + if (present(saln_scale)) then ; if (saln_scale /= 1.0) then + a2s = a2s * saln_scale + b4s = b4s * saln_scale ; b5s = b5s * saln_scale + c4s = c4s * saln_scale ; c5s = c5s * saln_scale + endif ; endif + do_massWeight = .false. if (present(useMassWghtInterp)) then ; if (useMassWghtInterp) then do_massWeight = .true. @@ -514,9 +554,9 @@ subroutine int_density_dz_wright(T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, & endif ; endif do j=Jsq,Jeq+1 ; do i=Isq,Ieq+1 - al0_2d(i,j) = (a0 + a1*T(i,j)) + a2*S(i,j) - p0_2d(i,j) = (b0 + b4*S(i,j)) + T(i,j) * (b1 + T(i,j)*((b2 + b3*T(i,j))) + b5*S(i,j)) - lambda_2d(i,j) = (c0 +c4*S(i,j)) + T(i,j) * (c1 + T(i,j)*((c2 + c3*T(i,j))) + c5*S(i,j)) + al0_2d(i,j) = (a0 + a1s*T(i,j)) + a2s*S(i,j) + p0_2d(i,j) = (b0 + b4s*S(i,j)) + T(i,j) * (b1s + T(i,j)*((b2s + b3s*T(i,j))) + b5s*S(i,j)) + lambda_2d(i,j) = (c0 +c4s*S(i,j)) + T(i,j) * (c1s + T(i,j)*((c2s + c3s*T(i,j))) + c5s*S(i,j)) al0 = al0_2d(i,j) ; p0 = p0_2d(i,j) ; lambda = lambda_2d(i,j) @@ -628,14 +668,14 @@ end subroutine int_density_dz_wright !! Boole's rule to do the horizontal integrals, and from a truncation in the !! series for log(1-eps/1+eps) that assumes that |eps| < 0.34. subroutine int_spec_vol_dp_wright(T, S, p_t, p_b, spv_ref, HI, dza, & - intp_dza, intx_dza, inty_dza, halo_size, & - bathyP, dP_neglect, useMassWghtInterp, SV_scale, pres_scale) + intp_dza, intx_dza, inty_dza, halo_size, bathyP, dP_neglect, & + useMassWghtInterp, SV_scale, pres_scale, temp_scale, saln_scale) type(hor_index_type), intent(in) :: HI !< The ocean's horizontal index type. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(in) :: T !< Potential temperature relative to the surface - !! [degC]. + !! [C ~> degC]. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & - intent(in) :: S !< Salinity [PSU]. + intent(in) :: S !< Salinity [S ~> PSU]. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(in) :: p_t !< Pressure at the top of the layer [R L2 T-2 ~> Pa] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & @@ -673,9 +713,15 @@ subroutine int_spec_vol_dp_wright(T, S, p_t, p_b, spv_ref, HI, dza, & !! volume from m3 kg-1 to the desired units [kg m-3 R-1 ~> 1] real, optional, intent(in) :: pres_scale !< A multiplicative factor to convert pressure !! into Pa [Pa T2 R-1 L-2 ~> 1]. + real, optional, intent(in) :: temp_scale !< A multiplicative factor by which to scale + !! temperature into degC [degC C-1 ~> 1] + real, optional, intent(in) :: saln_scale !< A multiplicative factor to convert pressure + !! into ppt [ppt S-1 ~> 1]. ! Local variables - real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed) :: al0_2d, p0_2d, lambda_2d + real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed) :: al0_2d ! A term in the Wright EOS [R-1 ~> m3 kg-1] + real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed) :: p0_2d ! A term in the Wright EOS [R L2 T-2 ~> Pa] + real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed) :: lambda_2d ! A term in the Wright EOS [L2 T-2 ~> m2 s-2] real :: al0 ! A term in the Wright EOS [R-1 ~> m3 kg-1] real :: p0 ! A term in the Wright EOS [R L2 T-2 ~> Pa] real :: lambda ! A term in the Wright EOS [L2 T-2 ~> m2 s-2] @@ -696,6 +742,18 @@ subroutine int_spec_vol_dp_wright(T, S, p_t, p_b, spv_ref, HI, dza, & real :: wtT_L, wtT_R ! The weights for tracers from the left and right columns [nondim]. real :: intp(5) ! The integrals of specific volume with pressure at the ! 5 sub-column locations [L2 T-2 ~> m2 s-2]. + real :: a1s ! Partly rescaled version of a1 [m3 kg-1 C-1 ~> m3 kg-1 degC-1] + real :: a2s ! Partly rescaled version of a2 [m3 kg-1 S-1 ~> m3 kg-1 ppt-1] + real :: b1s ! Partly rescaled version of b1 [Pa C-1 ~> Pa degC-1] + real :: b2s ! Partly rescaled version of b2 [Pa C-2 ~> Pa degC-2] + real :: b3s ! Partly rescaled version of b3 [Pa C-3 ~> Pa degC-3] + real :: b4s ! Partly rescaled version of b4 [Pa S-1 ~> Pa ppt-1] + real :: b5s ! Partly rescaled version of b5 [Pa C-1 S-1 ~> Pa degC-1 ppt-1] + real :: c1s ! Partly rescaled version of c1 [m2 s-2 C-1 ~> m2 s-2 degC-1] + real :: c2s ! Partly rescaled version of c2 [m2 s-2 C-2 ~> m2 s-2 degC-2] + real :: c3s ! Partly rescaled version of c3 [m2 s-2 C-3 ~> m2 s-2 degC-3] + real :: c4s ! Partly rescaled version of c4 [m2 s-2 S-1 ~> m2 s-2 ppt-1] + real :: c5s ! Partly rescaled version of c5 [m2 s-2 C-1 S-1 ~> m2 s-2 degC-1 ppt-1] logical :: do_massWeight ! Indicates whether to do mass weighting. real, parameter :: C1_3 = 1.0/3.0, C1_7 = 1.0/7.0 ! Rational constants. real, parameter :: C1_9 = 1.0/9.0, C1_90 = 1.0/90.0 ! Rational constants. @@ -715,6 +773,24 @@ subroutine int_spec_vol_dp_wright(T, S, p_t, p_b, spv_ref, HI, dza, & endif ; endif lam_scale = al0_scale * p0_scale + a1s = a1 ; a2s = a2 + b1s = b1 ; b2s = b2 ; b3s = b3 ; b4s = b4 ; b5s = b5 + c1s = c1 ; c2s = c2 ; c3s = c3 ; c4s = c4 ; c5s = c5 + + if (present(temp_scale)) then ; if (temp_scale /= 1.0) then + a1s = a1s * temp_scale + b1s = b1s * temp_scale ; b2s = b2s * temp_scale**2 + b3s = b3s * temp_scale**3 ; b5s = b5s * temp_scale + c1s = c1s * temp_scale ; c2s = c2s * temp_scale**2 + c3s = c3s * temp_scale**3 ; c5s = c5s * temp_scale + endif ; endif + + if (present(saln_scale)) then ; if (saln_scale /= 1.0) then + a2s = a2s * saln_scale + b4s = b4s * saln_scale ; b5s = b5s * saln_scale + c4s = c4s * saln_scale ; c5s = c5s * saln_scale + endif ; endif + do_massWeight = .false. if (present(useMassWghtInterp)) then ; if (useMassWghtInterp) then do_massWeight = .true. @@ -726,9 +802,9 @@ subroutine int_spec_vol_dp_wright(T, S, p_t, p_b, spv_ref, HI, dza, & ! alpha(j) = (lambda + al0*(pressure(j) + p0)) / (pressure(j) + p0) do j=jsh,jeh ; do i=ish,ieh - al0_2d(i,j) = al0_scale * ( (a0 + a1*T(i,j)) + a2*S(i,j) ) - p0_2d(i,j) = p0_scale * ( (b0 + b4*S(i,j)) + T(i,j) * (b1 + T(i,j)*((b2 + b3*T(i,j))) + b5*S(i,j)) ) - lambda_2d(i,j) = lam_scale * ( (c0 + c4*S(i,j)) + T(i,j) * (c1 + T(i,j)*((c2 + c3*T(i,j))) + c5*S(i,j)) ) + al0_2d(i,j) = al0_scale * ( (a0 + a1s*T(i,j)) + a2s*S(i,j) ) + p0_2d(i,j) = p0_scale * ( (b0 + b4s*S(i,j)) + T(i,j) * (b1s + T(i,j)*((b2s + b3s*T(i,j))) + b5s*S(i,j)) ) + lambda_2d(i,j) = lam_scale * ( (c0 + c4s*S(i,j)) + T(i,j) * (c1s + T(i,j)*((c2s + c3s*T(i,j))) + c5s*S(i,j)) ) al0 = al0_2d(i,j) ; p0 = p0_2d(i,j) ; lambda = lambda_2d(i,j) dp = p_b(i,j) - p_t(i,j) diff --git a/src/equation_of_state/MOM_EOS_linear.F90 b/src/equation_of_state/MOM_EOS_linear.F90 index 5650481558..2b4f99adf0 100644 --- a/src/equation_of_state/MOM_EOS_linear.F90 +++ b/src/equation_of_state/MOM_EOS_linear.F90 @@ -329,9 +329,9 @@ subroutine int_density_dz_linear(T, S, z_t, z_b, rho_ref, rho_0_pres, G_e, HI, & type(hor_index_type), intent(in) :: HI !< The horizontal index type for the arrays. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(in) :: T !< Potential temperature relative to the surface - !! [degC]. + !! [C ~> degC]. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & - intent(in) :: S !< Salinity [PSU]. + intent(in) :: S !< Salinity [S ?~> PSU]. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(in) :: z_t !< Height at the top of the layer in depth units [Z ~> m]. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & @@ -346,9 +346,9 @@ subroutine int_density_dz_linear(T, S, z_t, z_b, rho_ref, rho_0_pres, G_e, HI, & !! [L2 Z-1 T-2 ~> m s-2] real, intent(in) :: Rho_T0_S0 !< The density at T=0, S=0 [R ~> kg m-3] real, intent(in) :: dRho_dT !< The derivative of density with temperature, - !! [R degC-1 ~> kg m-3 degC-1] + !! [R C-1 ~> kg m-3 degC-1] real, intent(in) :: dRho_dS !< The derivative of density with salinity, - !! in [R ppt-1 ~> kg m-3 ppt-1] + !! in [R S-1 ~> kg m-3 ppt-1] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(out) :: dpa !< The change in the pressure anomaly across the !! layer [R L2 T-2 ~> Pa] @@ -500,9 +500,9 @@ subroutine int_spec_vol_dp_linear(T, S, p_t, p_b, alpha_ref, HI, Rho_T0_S0, & type(hor_index_type), intent(in) :: HI !< The ocean's horizontal index type. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(in) :: T !< Potential temperature relative to the surface - !! [degC]. + !! [C ~> degC]. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & - intent(in) :: S !< Salinity [PSU]. + intent(in) :: S !< Salinity [S ~> PSU]. real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(in) :: p_t !< Pressure at the top of the layer [R L2 T-2 ~> Pa] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & @@ -513,9 +513,9 @@ subroutine int_spec_vol_dp_linear(T, S, p_t, p_b, alpha_ref, HI, Rho_T0_S0, & !! alpha_ref, but this reduces the effects of roundoff. real, intent(in) :: Rho_T0_S0 !< The density at T=0, S=0 [R ~> kg m-3] real, intent(in) :: dRho_dT !< The derivative of density with temperature - !! [R degC-1 ~> kg m-3 degC-1] + !! [R C-1 ~> kg m-3 degC-1] real, intent(in) :: dRho_dS !< The derivative of density with salinity, - !! in [R ppt-1 ~> kg m-3 ppt-1] + !! in [R S-1 ~> kg m-3 ppt-1] real, dimension(HI%isd:HI%ied,HI%jsd:HI%jed), & intent(out) :: dza !< The change in the geopotential anomaly across !! the layer [L2 T-2 ~> m2 s-2] diff --git a/src/framework/MOM_diag_mediator.F90 b/src/framework/MOM_diag_mediator.F90 index 9f6b57fe6c..1f6b4133c0 100644 --- a/src/framework/MOM_diag_mediator.F90 +++ b/src/framework/MOM_diag_mediator.F90 @@ -306,8 +306,8 @@ module MOM_diag_mediator ! Pointer to H, G and T&S needed for remapping real, dimension(:,:,:), pointer :: h => null() !< The thicknesses needed for remapping [H ~> m or kg m-2] - real, dimension(:,:,:), pointer :: T => null() !< The temperatures needed for remapping [degC] - real, dimension(:,:,:), pointer :: S => null() !< The salinities needed for remapping [ppt] + real, dimension(:,:,:), pointer :: T => null() !< The temperatures needed for remapping [C ~> degC] + real, dimension(:,:,:), pointer :: S => null() !< The salinities needed for remapping [S ~> ppt] type(EOS_type), pointer :: eqn_of_state => null() !< The equation of state type type(ocean_grid_type), pointer :: G => null() !< The ocean grid type type(verticalGrid_type), pointer :: GV => null() !< The model's vertical ocean grid @@ -3335,8 +3335,8 @@ end subroutine diag_mediator_init !> Set pointers to the default state fields used to remap diagnostics. subroutine diag_set_state_ptrs(h, T, S, eqn_of_state, diag_cs) real, dimension(:,:,:), target, intent(in ) :: h !< the model thickness array [H ~> m or kg m-2] - real, dimension(:,:,:), target, intent(in ) :: T !< the model temperature array - real, dimension(:,:,:), target, intent(in ) :: S !< the model salinity array + real, dimension(:,:,:), target, intent(in ) :: T !< the model temperature array [C ~> degC] + real, dimension(:,:,:), target, intent(in ) :: S !< the model salinity array [S ~> ppt] type(EOS_type), target, intent(in ) :: eqn_of_state !< Equation of state structure type(diag_ctrl), intent(inout) :: diag_cs !< diag mediator control structure @@ -3356,9 +3356,9 @@ subroutine diag_update_remap_grids(diag_cs, alt_h, alt_T, alt_S, update_intensiv real, target, optional, intent(in ) :: alt_h(:,:,:) !< Used if remapped grids should be something other than !! the current thicknesses [H ~> m or kg m-2] real, target, optional, intent(in ) :: alt_T(:,:,:) !< Used if remapped grids should be something other than - !! the current temperatures + !! the current temperatures [C ~> degC] real, target, optional, intent(in ) :: alt_S(:,:,:) !< Used if remapped grids should be something other than - !! the current salinity + !! the current salinity [S ~> ppt] logical, optional, intent(in ) :: update_intensive !< If true (default), update the grids used for !! intensive diagnostics logical, optional, intent(in ) :: update_extensive !< If true (not default), update the grids used for @@ -3366,7 +3366,8 @@ subroutine diag_update_remap_grids(diag_cs, alt_h, alt_T, alt_S, update_intensiv ! Local variables integer :: i real, dimension(:,:,:), pointer :: h_diag => NULL() ! The layer thickneses for diagnostics [H ~> m or kg m-2] - real, dimension(:,:,:), pointer :: T_diag => NULL(), S_diag => NULL() + real, dimension(:,:,:), pointer :: T_diag => NULL() ! The layer temperatures for diagnostics [C ~> degC] + real, dimension(:,:,:), pointer :: S_diag => NULL() ! The layer salinities for diagnostics [S ~> ppt] logical :: update_intensive_local, update_extensive_local ! Set values based on optional input arguments diff --git a/src/framework/MOM_diag_remap.F90 b/src/framework/MOM_diag_remap.F90 index b665dcd748..2f179a3825 100644 --- a/src/framework/MOM_diag_remap.F90 +++ b/src/framework/MOM_diag_remap.F90 @@ -273,8 +273,8 @@ subroutine diag_remap_update(remap_cs, G, GV, US, h, T, S, eqn_of_state, h_targe type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type real, dimension(:,:,:), intent(in) :: h !< New thickness [H ~> m or kg m-2] - real, dimension(:,:,:), intent(in) :: T !< New temperatures [degC] - real, dimension(:,:,:), intent(in) :: S !< New salinities [ppt] + real, dimension(:,:,:), intent(in) :: T !< New temperatures [C ~> degC] + real, dimension(:,:,:), intent(in) :: S !< New salinities [S ~> ppt] type(EOS_type), intent(in) :: eqn_of_state !< A pointer to the equation of state real, dimension(:,:,:), intent(inout) :: h_target !< The new diagnostic thicknesses [H ~> m or kg m-2] diff --git a/src/framework/MOM_unit_scaling.F90 b/src/framework/MOM_unit_scaling.F90 index bf8fd24b44..6defa492a8 100644 --- a/src/framework/MOM_unit_scaling.F90 +++ b/src/framework/MOM_unit_scaling.F90 @@ -30,6 +30,10 @@ module MOM_unit_scaling real :: kg_m3_to_R !< A constant that translates kilograms per meter cubed to the units of density [R m3 kg-1 ~> 1] real :: Q_to_J_kg !< A constant that translates the units of enthalpy to Joules per kilogram [J kg-1 Q-1 ~> 1] real :: J_kg_to_Q !< A constant that translates Joules per kilogram to the units of enthalpy [Q kg J-1 ~> 1] + real :: C_to_degC !< A constant that translates the units of temperature to degrees Celsius [degC C-1 ~> 1] + real :: degC_to_C !< A constant that translates degrees Celsius to the units of temperature [C degC-1 ~> 1] + real :: S_to_ppt !< A constant that translates the units of salinity to parts per thousand [ppt S-1 ~> 1] + real :: ppt_to_S !< A constant that translates parts per thousand to the units of salinity [S ppt-1 ~> 1] ! These are useful combinations of the fundamental scale conversion factors above. real :: Z_to_L !< Convert vertical distances to lateral lengths [L Z-1 ~> 1] @@ -68,8 +72,9 @@ subroutine unit_scaling_init( param_file, US ) ! This routine initializes a unit_scale_type structure (US). ! Local variables - integer :: Z_power, L_power, T_power, R_power, Q_power + integer :: Z_power, L_power, T_power, R_power, Q_power, C_power, S_power real :: Z_rescale_factor, L_rescale_factor, T_rescale_factor, R_rescale_factor, Q_rescale_factor + real :: C_rescale_factor, S_rescale_factor ! This include declares and sets the variable "version". # include "version_variable.h" character(len=16) :: mdl = "MOM_unit_scaling" @@ -99,8 +104,16 @@ subroutine unit_scaling_init( param_file, US ) units="nondim", default=0, debuggingParam=.true.) call get_param(param_file, mdl, "Q_RESCALE_POWER", Q_power, & "An integer power of 2 that is used to rescale the model's "//& - "internal units of heat content. Valid values range from -300 to 300.", & - units="nondim", default=0, debuggingParam=.true.) + "internal units of heat content. Valid values range from -300 to 300.", & + units="nondim", default=0, debuggingParam=.true.) + call get_param(param_file, mdl, "C_RESCALE_POWER", C_power, & + "An integer power of 2 that is used to rescale the model's "//& + "internal units of temperature. Valid values range from -300 to 300.", & + units="nondim", default=0, debuggingParam=.true.) + call get_param(param_file, mdl, "S_RESCALE_POWER", S_power, & + "An integer power of 2 that is used to rescale the model's "//& + "internal units of salinity. Valid values range from -300 to 300.", & + units="nondim", default=0, debuggingParam=.true.) if (abs(Z_power) > 300) call MOM_error(FATAL, "unit_scaling_init: "//& "Z_RESCALE_POWER is outside of the valid range of -300 to 300.") @@ -112,6 +125,10 @@ subroutine unit_scaling_init( param_file, US ) "R_RESCALE_POWER is outside of the valid range of -300 to 300.") if (abs(Q_power) > 300) call MOM_error(FATAL, "unit_scaling_init: "//& "Q_RESCALE_POWER is outside of the valid range of -300 to 300.") + if (abs(C_power) > 300) call MOM_error(FATAL, "unit_scaling_init: "//& + "C_RESCALE_POWER is outside of the valid range of -300 to 300.") + if (abs(S_power) > 300) call MOM_error(FATAL, "unit_scaling_init: "//& + "S_RESCALE_POWER is outside of the valid range of -300 to 300.") Z_rescale_factor = 1.0 if (Z_power /= 0) Z_rescale_factor = 2.0**Z_power @@ -138,6 +155,16 @@ subroutine unit_scaling_init( param_file, US ) US%Q_to_J_kg = 1.0 * Q_Rescale_factor US%J_kg_to_Q = 1.0 / Q_Rescale_factor + C_Rescale_factor = 1.0 + if (C_power /= 0) C_Rescale_factor = 2.0**C_power + US%C_to_degC = 1.0 * C_Rescale_factor + US%degC_to_C = 1.0 / C_Rescale_factor + + S_Rescale_factor = 1.0 + if (S_power /= 0) S_Rescale_factor = 2.0**S_power + US%S_to_ppt = 1.0 * S_Rescale_factor + US%ppt_to_S = 1.0 / S_Rescale_factor + call set_unit_scaling_combos(US) end subroutine unit_scaling_init @@ -154,6 +181,8 @@ subroutine unit_no_scaling_init(US) US%T_to_s = 1.0 ; US%s_to_T = 1.0 US%R_to_kg_m3 = 1.0 ; US%kg_m3_to_R = 1.0 US%Q_to_J_kg = 1.0 ; US%J_kg_to_Q = 1.0 + US%C_to_degC = 1.0 ; US%degC_to_C = 1.0 + US%S_to_ppt = 1.0 ; US%ppt_to_S = 1.0 call set_unit_scaling_combos(US) end subroutine unit_no_scaling_init diff --git a/src/ice_shelf/MOM_ice_shelf.F90 b/src/ice_shelf/MOM_ice_shelf.F90 index 10aef884dd..a1766e7805 100644 --- a/src/ice_shelf/MOM_ice_shelf.F90 +++ b/src/ice_shelf/MOM_ice_shelf.F90 @@ -244,9 +244,9 @@ subroutine shelf_calc_flux(sfc_state_in, fluxes_in, Time, time_step, CS) real, dimension(SZI_(CS%grid)) :: & Rhoml, & !< Ocean mixed layer density [R ~> kg m-3]. dR0_dT, & !< Partial derivative of the mixed layer density - !< with temperature [R degC-1 ~> kg m-3 degC-1]. + !< with temperature [R C-1 ~> kg m-3 degC-1]. dR0_dS, & !< Partial derivative of the mixed layer density - !< with salinity [R ppt-1 ~> kg m-3 ppt-1]. + !< with salinity [R S-1 ~> kg m-3 ppt-1]. p_int !< The pressure at the ice-ocean interface [R L2 T-2 ~> Pa]. real, dimension(SZI_(CS%grid),SZJ_(CS%grid)) :: & @@ -426,10 +426,10 @@ subroutine shelf_calc_flux(sfc_state_in, fluxes_in, Time, time_step, CS) do i=is,ie ; p_int(i) = CS%g_Earth * ISS%mass_shelf(i,j) ; enddo ! Calculate insitu densities and expansion coefficients - call calculate_density(sfc_state%sst(:,j), sfc_state%sss(:,j), p_int, Rhoml(:), & - CS%eqn_of_state, EOSdom) - call calculate_density_derivs(sfc_state%sst(:,j), sfc_state%sss(:,j), p_int, dR0_dT, dR0_dS, & + call calculate_density(US%degC_to_C*sfc_state%sst(:,j), US%ppt_to_S*sfc_state%sss(:,j), p_int, Rhoml(:), & CS%eqn_of_state, EOSdom) + call calculate_density_derivs(US%degC_to_C*sfc_state%sst(:,j), US%ppt_to_S*sfc_state%sss(:,j), p_int, & + dR0_dT, dR0_dS, CS%eqn_of_state, EOSdom) do i=is,ie if ((sfc_state%ocean_mass(i,j) > CS%col_mass_melt_threshold) .and. & @@ -451,8 +451,8 @@ subroutine shelf_calc_flux(sfc_state_in, fluxes_in, Time, time_step, CS) hBL_neut_h_molec = ZETA_N * ((hBL_neut * ustar_h) / (5.0 * CS%kv_molec)) ! Determine the mixed layer buoyancy flux, wB_flux. - dB_dS = (US%L_to_Z**2*CS%g_Earth / Rhoml(i)) * dR0_dS(i) - dB_dT = (US%L_to_Z**2*CS%g_Earth / Rhoml(i)) * dR0_dT(i) + dB_dS = (US%L_to_Z**2*CS%g_Earth / Rhoml(i)) * US%ppt_to_S*dR0_dS(i) + dB_dT = (US%L_to_Z**2*CS%g_Earth / Rhoml(i)) * US%degC_to_C*dR0_dT(i) ln_neut = 0.0 ; if (hBL_neut_h_molec > 1.0) ln_neut = log(hBL_neut_h_molec) if (CS%find_salt_root) then diff --git a/src/initialization/MOM_coord_initialization.F90 b/src/initialization/MOM_coord_initialization.F90 index 310a7f9392..cb5d0ca81b 100644 --- a/src/initialization/MOM_coord_initialization.F90 +++ b/src/initialization/MOM_coord_initialization.F90 @@ -204,8 +204,8 @@ subroutine set_coord_from_TS_ref(Rlay, g_prime, GV, US, param_file, eqn_of_state !! [R L2 T-2 ~> Pa]. ! Local variables - real :: T_ref ! Reference temperature - real :: S_ref ! Reference salinity + real :: T_ref ! Reference temperature [C ~> degC] + real :: S_ref ! Reference salinity [S ~> ppt] real :: g_int ! Reduced gravities across the internal interfaces [L2 Z-1 T-2 ~> m s-2]. real :: g_fs ! Reduced gravity across the free surface [L2 Z-1 T-2 ~> m s-2]. character(len=40) :: mdl = "set_coord_from_TS_ref" ! This subroutine's name. @@ -214,11 +214,11 @@ subroutine set_coord_from_TS_ref(Rlay, g_prime, GV, US, param_file, eqn_of_state call callTree_enter(trim(mdl)//"(), MOM_coord_initialization.F90") - call get_param(param_file, mdl, "T_REF", T_Ref, & - "The initial temperature of the lightest layer.", units="degC", & - fail_if_missing=.true.) - call get_param(param_file, mdl, "S_REF", S_Ref, & - "The initial salinities.", units="PSU", default=35.0) + call get_param(param_file, mdl, "T_REF", T_ref, & + "The initial temperature of the lightest layer.", & + units="degC", scale=US%degC_to_C, fail_if_missing=.true.) + call get_param(param_file, mdl, "S_REF", S_ref, & + "The initial salinities.", units="PSU", default=35.0, scale=US%ppt_to_S) call get_param(param_file, mdl, "GFS", g_fs, & "The reduced gravity at the free surface.", units="m s-2", & default=GV%g_Earth*US%L_T_to_m_s**2*US%m_to_Z, scale=US%m_s_to_L_T**2*US%Z_to_m) @@ -254,7 +254,9 @@ subroutine set_coord_from_TS_profile(Rlay, g_prime, GV, US, param_file, eqn_of_s !! [R L2 T-2 ~> Pa]. ! Local variables - real, dimension(GV%ke) :: T0, S0, Pref + real, dimension(GV%ke) :: T0 ! A profile of temperatures [C ~> degC] + real, dimension(GV%ke) :: S0 ! A profile of salinities [S ~> ppt] + real, dimension(GV%ke) :: Pref ! A array of reference pressures [R L2 T-2 ~> Pa] real :: g_fs ! Reduced gravity across the free surface [L2 Z-1 T-2 ~> m s-2]. integer :: k, nz character(len=40) :: mdl = "set_coord_from_TS_profile" ! This subroutine's name. @@ -274,8 +276,8 @@ subroutine set_coord_from_TS_profile(Rlay, g_prime, GV, US, param_file, eqn_of_s filename = trim(slasher(inputdir))//trim(coord_file) call log_param(param_file, mdl, "INPUTDIR/COORD_FILE", filename) - call MOM_read_data(filename, "PTEMP", T0(:)) - call MOM_read_data(filename, "SALT", S0(:)) + call MOM_read_data(filename, "PTEMP", T0(:), scale=US%degC_to_C) + call MOM_read_data(filename, "SALT", S0(:), scale=US%ppt_to_S) if (.not.file_exists(filename)) call MOM_error(FATAL, & " set_coord_from_TS_profile: Unable to open " //trim(filename)) @@ -301,9 +303,13 @@ subroutine set_coord_from_TS_range(Rlay, g_prime, GV, US, param_file, eqn_of_sta !! [R L2 T-2 ~> Pa]. ! Local variables - real, dimension(GV%ke) :: T0, S0, Pref - real :: S_Ref, S_Light, S_Dense ! Salinity range parameters [ppt]. - real :: T_Ref, T_Light, T_Dense ! Temperature range parameters [degC]. + real, dimension(GV%ke) :: T0 ! A profile of temperatures [C ~> degC] + real, dimension(GV%ke) :: S0 ! A profile of salinities [S ~> ppt] + real, dimension(GV%ke) :: Pref ! A array of reference pressures [R L2 T-2 ~> Pa] + real :: S_Ref ! Default salinity range parameters [ppt]. + real :: T_Ref ! Default temperature range parameters [degC]. + real :: S_Light, S_Dense ! Salinity range parameters [S ~> ppt]. + real :: T_Light, T_Dense ! Temperature range parameters [C ~> degC]. real :: res_rat ! The ratio of density space resolution in the denser part ! of the range to that in the lighter part of the range. ! Setting this greater than 1 increases the resolution for @@ -321,19 +327,19 @@ subroutine set_coord_from_TS_range(Rlay, g_prime, GV, US, param_file, eqn_of_sta "The default initial temperatures.", units="degC", default=10.0) call get_param(param_file, mdl, "TS_RANGE_T_LIGHT", T_Light, & "The initial temperature of the lightest layer when "//& - "COORD_CONFIG is set to ts_range.", units="degC", default=T_Ref) + "COORD_CONFIG is set to ts_range.", units="degC", default=T_Ref, scale=US%degC_to_C) call get_param(param_file, mdl, "TS_RANGE_T_DENSE", T_Dense, & "The initial temperature of the densest layer when "//& - "COORD_CONFIG is set to ts_range.", units="degC", default=T_Ref) + "COORD_CONFIG is set to ts_range.", units="degC", default=T_Ref, scale=US%degC_to_C) call get_param(param_file, mdl, "S_REF", S_Ref, & "The default initial salinities.", units="PSU", default=35.0) call get_param(param_file, mdl, "TS_RANGE_S_LIGHT", S_Light, & "The initial lightest salinities when COORD_CONFIG "//& - "is set to ts_range.", default = S_Ref, units="PSU") + "is set to ts_range.", default = S_Ref, units="PSU", scale=US%ppt_to_S) call get_param(param_file, mdl, "TS_RANGE_S_DENSE", S_Dense, & "The initial densest salinities when COORD_CONFIG "//& - "is set to ts_range.", default = S_Ref, units="PSU") + "is set to ts_range.", default = S_Ref, units="PSU", scale=US%ppt_to_S) call get_param(param_file, mdl, "TS_RANGE_RESOLN_RATIO", res_rat, & "The ratio of density space resolution in the densest "//& @@ -352,7 +358,7 @@ subroutine set_coord_from_TS_range(Rlay, g_prime, GV, US, param_file, eqn_of_sta k_light = GV%nk_rho_varies + 1 ! Set T0(k) to range from T_LIGHT to T_DENSE, and simliarly for S0(k). - T0(k_light) = T_light ; S0(k_light) = S_light + T0(k_light) = T_Light ; S0(k_light) = S_Light a1 = 2.0 * res_rat / (1.0 + res_rat) do k=k_light+1,nz k_frac = real(k-k_light)/real(nz-k_light) diff --git a/src/initialization/MOM_state_initialization.F90 b/src/initialization/MOM_state_initialization.F90 index ae7a23c3c9..829368efbc 100644 --- a/src/initialization/MOM_state_initialization.F90 +++ b/src/initialization/MOM_state_initialization.F90 @@ -366,33 +366,33 @@ subroutine MOM_initialize_state(u, v, h, tv, Time, G, GV, US, PF, dirs, & select case (trim(config)) case ("fit"); call initialize_temp_salt_fit(tv%T, tv%S, G, GV, US, PF, & eos, tv%P_Ref, just_read=just_read) - case ("file"); call initialize_temp_salt_from_file(tv%T, tv%S, G, GV, & + case ("file"); call initialize_temp_salt_from_file(tv%T, tv%S, G, GV, US, & PF, just_read=just_read) case ("benchmark"); call benchmark_init_temperature_salinity(tv%T, tv%S, & G, GV, US, PF, eos, tv%P_Ref, just_read=just_read) case ("TS_profile") ; call initialize_temp_salt_from_profile(tv%T, tv%S, & - G, GV, PF, just_read=just_read) - case ("linear"); call initialize_temp_salt_linear(tv%T, tv%S, G, GV, PF, & + G, GV, US, PF, just_read=just_read) + case ("linear"); call initialize_temp_salt_linear(tv%T, tv%S, G, GV, US, PF, & just_read=just_read) - case ("DOME2D"); call DOME2d_initialize_temperature_salinity ( tv%T, & - tv%S, h, G, GV, PF, just_read=just_read) - case ("ISOMIP"); call ISOMIP_initialize_temperature_salinity ( tv%T, & - tv%S, h, depth_tot, G, GV, US, PF, eos, just_read=just_read) + case ("DOME2D"); call DOME2d_initialize_temperature_salinity (tv%T, tv%S, h, & + G, GV, US, PF, just_read=just_read) + case ("ISOMIP"); call ISOMIP_initialize_temperature_salinity (tv%T, tv%S, h, & + depth_tot, G, GV, US, PF, eos, just_read=just_read) case ("adjustment2d"); call adjustment_initialize_temperature_salinity ( tv%T, & - tv%S, h, depth_tot, G, GV, PF, just_read=just_read) + tv%S, h, depth_tot, G, GV, US, PF, just_read=just_read) case ("baroclinic_zone"); call baroclinic_zone_init_temperature_salinity( tv%T, & tv%S, h, depth_tot, G, GV, US, PF, just_read=just_read) case ("sloshing"); call sloshing_initialize_temperature_salinity(tv%T, & - tv%S, h, G, GV, PF, just_read=just_read) + tv%S, h, G, GV, US, PF, just_read=just_read) case ("seamount"); call seamount_initialize_temperature_salinity(tv%T, & - tv%S, h, G, GV, PF, just_read=just_read) + tv%S, h, G, GV, US, PF, just_read=just_read) case ("dumbbell"); call dumbbell_initialize_temperature_salinity(tv%T, & - tv%S, h, G, GV, PF, just_read=just_read) + tv%S, h, G, GV, US, PF, just_read=just_read) case ("rossby_front"); call Rossby_front_initialize_temperature_salinity ( tv%T, & - tv%S, h, G, GV, PF, just_read=just_read) + tv%S, h, G, GV, US, PF, just_read=just_read) case ("SCM_CVMix_tests"); call SCM_CVMix_tests_TS_init(tv%T, tv%S, h, & G, GV, US, PF, just_read=just_read) - case ("dense"); call dense_water_initialize_TS(G, GV, PF, tv%T, tv%S, & + case ("dense"); call dense_water_initialize_TS(G, GV, US, PF, tv%T, tv%S, & h, just_read=just_read) case ("USER"); call user_init_temperature_salinity(tv%T, tv%S, G, GV, PF, & just_read=just_read) @@ -402,7 +402,7 @@ subroutine MOM_initialize_state(u, v, h, tv, Time, G, GV, US, PF, dirs, & endif endif ! not from_Z_file. if (use_temperature .and. use_OBC) & - call fill_temp_salt_segments(G, GV, OBC, tv) + call fill_temp_salt_segments(G, GV, US, OBC, tv) ! Calculate the initial surface displacement under ice shelf @@ -548,13 +548,13 @@ subroutine MOM_initialize_state(u, v, h, tv, Time, G, GV, US, PF, dirs, & if (debug) then call hchksum(h, "MOM_initialize_state: h ", G%HI, haloshift=1, scale=GV%H_to_m) - if ( use_temperature ) call hchksum(tv%T, "MOM_initialize_state: T ", G%HI, haloshift=1) - if ( use_temperature ) call hchksum(tv%S, "MOM_initialize_state: S ", G%HI, haloshift=1) + if ( use_temperature ) call hchksum(tv%T, "MOM_initialize_state: T ", G%HI, haloshift=1, scale=US%C_to_degC) + if ( use_temperature ) call hchksum(tv%S, "MOM_initialize_state: S ", G%HI, haloshift=1, scale=US%S_to_ppt) if ( use_temperature .and. debug_layers) then ; do k=1,nz write(mesg,'("MOM_IS: T[",I2,"]")') k - call hchksum(tv%T(:,:,k), mesg, G%HI, haloshift=1) + call hchksum(tv%T(:,:,k), mesg, G%HI, haloshift=1, scale=US%C_to_degC) write(mesg,'("MOM_IS: S[",I2,"]")') k - call hchksum(tv%S(:,:,k), mesg, G%HI, haloshift=1) + call hchksum(tv%S(:,:,k), mesg, G%HI, haloshift=1, scale=US%S_to_ppt) enddo ; endif endif @@ -1160,7 +1160,9 @@ subroutine trim_for_ice(PF, G, GV, US, ALE_CSp, tv, h, just_read) character(len=200) :: mdl = "trim_for_ice" real, dimension(SZI_(G),SZJ_(G)) :: p_surf ! Imposed pressure on ocean at surface [R L2 T-2 ~> Pa] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: S_t, S_b ! Top and bottom edge values for reconstructions - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: T_t, T_b ! of salinity [ppt] and temperature [degC] within each layer. + ! of salinity within each layer [S ~> ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: T_t, T_b ! Top and bottom edge values for reconstructions + ! of temperature within each layer [T ~> degC] character(len=200) :: inputdir, filename, p_surf_file, p_surf_var ! Strings for file/path real :: scale_factor ! A file-dependent scaling factor for the input pressure. real :: min_thickness ! The minimum layer thickness, recast into Z units [Z ~> m]. @@ -1323,12 +1325,12 @@ subroutine cut_off_column_top(nk, tv, GV, US, G_earth, depth, min_thickness, T, real, intent(in) :: G_earth !< Gravitational acceleration [L2 Z-1 T-2 ~> m s-2] real, intent(in) :: depth !< Depth of ocean column [Z ~> m]. real, intent(in) :: min_thickness !< Smallest thickness allowed [Z ~> m]. - real, dimension(nk), intent(inout) :: T !< Layer mean temperature [degC] - real, dimension(nk), intent(in) :: T_t !< Temperature at top of layer [degC] - real, dimension(nk), intent(in) :: T_b !< Temperature at bottom of layer [degC] - real, dimension(nk), intent(inout) :: S !< Layer mean salinity [ppt] - real, dimension(nk), intent(in) :: S_t !< Salinity at top of layer [ppt] - real, dimension(nk), intent(in) :: S_b !< Salinity at bottom of layer [ppt] + real, dimension(nk), intent(inout) :: T !< Layer mean temperature [C ~> degC] + real, dimension(nk), intent(in) :: T_t !< Temperature at top of layer [C ~> degC] + real, dimension(nk), intent(in) :: T_b !< Temperature at bottom of layer [C ~> degC] + real, dimension(nk), intent(inout) :: S !< Layer mean salinity [S ~> ppt] + real, dimension(nk), intent(in) :: S_t !< Salinity at top of layer [S ~> ppt] + real, dimension(nk), intent(in) :: S_b !< Salinity at bottom of layer [S ~> ppt] real, intent(in) :: p_surf !< Imposed pressure on ocean at surface [R L2 T-2 ~> Pa] real, dimension(nk), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2] type(remapping_CS), pointer :: remap_CS !< Remapping structure for remapping T and S, @@ -1587,13 +1589,14 @@ end function my_psi end subroutine initialize_velocity_circular !> Initializes temperature and salinity from file -subroutine initialize_temp_salt_from_file(T, S, G, GV, param_file, just_read) +subroutine initialize_temp_salt_from_file(T, S, G, GV, US, param_file, just_read) 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(out) :: T !< The potential temperature that is - !! being initialized [degC] + !! being initialized [C ~> degC] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< The salinity that is - !! being initialized [ppt] + !! being initialized [S ~> ppt] + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters logical, intent(in) :: just_read !< If true, this call will only !! read parameters without changing T or S. @@ -1629,27 +1632,28 @@ subroutine initialize_temp_salt_from_file(T, S, G, GV, param_file, just_read) " initialize_temp_salt_from_file: Unable to open "//trim(filename)) ! Read the temperatures and salinities from netcdf files. - call MOM_read_data(filename, temp_var, T(:,:,:), G%Domain) + call MOM_read_data(filename, temp_var, T(:,:,:), G%Domain, scale=US%degC_to_C) salt_filename = trim(inputdir)//trim(salt_file) if (.not.file_exists(salt_filename, G%Domain)) call MOM_error(FATAL, & " initialize_temp_salt_from_file: Unable to open "//trim(salt_filename)) - call MOM_read_data(salt_filename, salt_var, S(:,:,:), G%Domain) + call MOM_read_data(salt_filename, salt_var, S(:,:,:), G%Domain, scale=US%ppt_to_S) call callTree_leave(trim(mdl)//'()') end subroutine initialize_temp_salt_from_file !> Initializes temperature and salinity from a 1D profile -subroutine initialize_temp_salt_from_profile(T, S, G, GV, param_file, just_read) +subroutine initialize_temp_salt_from_profile(T, S, G, GV, US, param_file, just_read) 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(out) :: T !< The potential temperature that is - !! being initialized [degC] + !! being initialized [C ~> degC] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< The salinity that is - !! being initialized [ppt] - type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters - logical, intent(in) :: just_read !< If true, this call will only read + !! being initialized [S ~> ppt] + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type + type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters + logical, intent(in) :: just_read !< If true, this call will only read !! parameters without changing T or S. ! Local variables real, dimension(SZK_(GV)) :: T0, S0 @@ -1673,8 +1677,8 @@ subroutine initialize_temp_salt_from_profile(T, S, G, GV, param_file, just_read) " initialize_temp_salt_from_profile: Unable to open "//trim(filename)) ! Read the temperatures and salinities from a netcdf file. - call MOM_read_data(filename, "PTEMP", T0(:)) - call MOM_read_data(filename, "SALT", S0(:)) + call MOM_read_data(filename, "PTEMP", T0(:), scale=US%degC_to_C) + call MOM_read_data(filename, "SALT", S0(:), scale=US%ppt_to_S) do k=1,GV%ke ; do j=G%jsc,G%jec ; do i=G%isc,G%iec T(i,j,k) = T0(k) ; S(i,j,k) = S0(k) @@ -1688,9 +1692,9 @@ subroutine initialize_temp_salt_fit(T, S, G, GV, US, param_file, eqn_of_state, P 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(out) :: T !< The potential temperature that is - !! being initialized [degC]. + !! being initialized [C ~> degC]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< The salinity that is being - !! initialized [ppt]. + !! initialized [S ~> ppt]. type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time !! parameters. @@ -1700,13 +1704,13 @@ subroutine initialize_temp_salt_fit(T, S, G, GV, US, param_file, eqn_of_state, P logical, intent(in) :: just_read !< If true, this call will only read !! parameters without changing T or S. ! Local variables - real :: T0(SZK_(GV)) ! Layer potential temperatures [degC] - real :: S0(SZK_(GV)) ! Layer salinities [degC] - real :: T_Ref ! Reference Temperature [degC] - real :: S_Ref ! Reference Salinity [ppt] + real :: T0(SZK_(GV)) ! Layer potential temperatures [C ~> degC] + real :: S0(SZK_(GV)) ! Layer salinities [S ~> ppt] + real :: T_Ref ! Reference Temperature [C ~> degC] + real :: S_Ref ! Reference Salinity [S ~> ppt] real :: pres(SZK_(GV)) ! An array of the reference pressure [R L2 T-2 ~> Pa]. - real :: drho_dT(SZK_(GV)) ! Derivative of density with temperature [R degC-1 ~> kg m-3 degC-1]. - real :: drho_dS(SZK_(GV)) ! Derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1]. + real :: drho_dT(SZK_(GV)) ! Derivative of density with temperature [R C-1 ~> kg m-3 degC-1]. + real :: drho_dS(SZK_(GV)) ! Derivative of density with salinity [R S-1 ~> kg m-3 ppt-1]. real :: rho_guess(SZK_(GV)) ! Potential density at T0 & S0 [R ~> kg m-3]. logical :: fit_salin ! If true, accept the prescribed temperature and fit the salinity. character(len=40) :: mdl = "initialize_temp_salt_fit" ! This subroutine's name. @@ -1717,10 +1721,10 @@ subroutine initialize_temp_salt_fit(T, S, G, GV, US, param_file, eqn_of_state, P call get_param(param_file, mdl, "T_REF", T_Ref, & "A reference temperature used in initialization.", & - units="degC", fail_if_missing=.not.just_read, do_not_log=just_read) + units="degC", scale=US%degC_to_C, fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl, "S_REF", S_Ref, & "A reference salinity used in initialization.", units="PSU", & - default=35.0, do_not_log=just_read) + default=35.0, scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl, "FIT_SALINITY", fit_salin, & "If true, accept the prescribed temperature and fit the "//& "salinity; otherwise take salinity and fit temperature.", & @@ -1775,13 +1779,14 @@ end subroutine initialize_temp_salt_fit !! !! \remark Note that the linear distribution is set up with respect to the layer !! number, not the physical position). -subroutine initialize_temp_salt_linear(T, S, G, GV, param_file, just_read) +subroutine initialize_temp_salt_linear(T, S, G, GV, US, param_file, just_read) 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(out) :: T !< The potential temperature that is - !! being initialized [degC] + !! being initialized [C ~> degC] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< The salinity that is - !! being initialized [ppt] + !! being initialized [S ~> ppt] + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< A structure to parse for !! run-time parameters logical, intent(in) :: just_read !< If present and true, @@ -1789,8 +1794,8 @@ subroutine initialize_temp_salt_linear(T, S, G, GV, param_file, just_read) !! without changing T or S. integer :: k - real :: S_top, T_top ! Reference salinity and temperature within surface layer - real :: S_range, T_range ! Range of salinities and temperatures over the vertical + real :: S_top, T_top ! Reference salinity [S ~> ppt] and temperature [C ~> degC] within surface layer + real :: S_range, T_range ! Range of salinities [S ~> ppt] and temperatures [C ~> degC] over the vertical !real :: delta_S, delta_T !real :: delta character(len=40) :: mdl = "initialize_temp_salt_linear" ! This subroutine's name. @@ -1798,16 +1803,16 @@ subroutine initialize_temp_salt_linear(T, S, G, GV, param_file, just_read) if (.not.just_read) call callTree_enter(trim(mdl)//"(), MOM_state_initialization.F90") call get_param(param_file, mdl, "T_TOP", T_top, & "Initial temperature of the top surface.", & - units="degC", fail_if_missing=.not.just_read, do_not_log=just_read) + units="degC", scale=US%degC_to_C, fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl, "T_RANGE", T_range, & "Initial temperature difference (top-bottom).", & - units="degC", fail_if_missing=.not.just_read, do_not_log=just_read) + units="degC", scale=US%degC_to_C, fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl, "S_TOP", S_top, & "Initial salinity of the top surface.", & - units="PSU", fail_if_missing=.not.just_read, do_not_log=just_read) + units="PSU", scale=US%ppt_to_S, fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl, "S_RANGE", S_range, & "Initial salinity difference (top-bottom).", & - units="PSU", fail_if_missing=.not.just_read, do_not_log=just_read) + units="PSU", scale=US%ppt_to_S, fail_if_missing=.not.just_read, do_not_log=just_read) if (just_read) return ! All run-time parameters have been read, so return. @@ -2046,8 +2051,8 @@ subroutine initialize_sponges_file(G, GV, US, use_temperature, tv, u, v, depth_t do i=is-1,ie ; pres(i) = tv%P_Ref ; enddo EOSdom(:) = EOS_domain(G%HI) - call MOM_read_data(filename, potemp_var, tmp(:,:,:), G%Domain) - call MOM_read_data(filename, salin_var, tmp2(:,:,:), G%Domain) + call MOM_read_data(filename, potemp_var, tmp(:,:,:), G%Domain, scale=US%degC_to_C) + call MOM_read_data(filename, salin_var, tmp2(:,:,:), G%Domain, scale=US%ppt_to_S) do j=js,je call calculate_density(tmp(:,j,1), tmp2(:,j,1), pres, tmp_2d(:,j), tv%eqn_of_state, EOSdom) @@ -2063,9 +2068,9 @@ subroutine initialize_sponges_file(G, GV, US, use_temperature, tv, u, v, depth_t ! The remaining calls to set_up_sponge_field can be in any order. if ( use_temperature) then - call MOM_read_data(filename, potemp_var, tmp(:,:,:), G%Domain) + call MOM_read_data(filename, potemp_var, tmp(:,:,:), G%Domain, scale=US%degC_to_C) call set_up_sponge_field(tmp, tv%T, G, GV, nz, Layer_CSp) - call MOM_read_data(filename, salin_var, tmp(:,:,:), G%Domain) + call MOM_read_data(filename, salin_var, tmp(:,:,:), G%Domain, scale=US%ppt_to_S) call set_up_sponge_field(tmp, tv%S, G, GV, nz, Layer_CSp) endif @@ -2107,9 +2112,9 @@ subroutine initialize_sponges_file(G, GV, US, use_temperature, tv, u, v, depth_t deallocate(h) if (use_temperature) then allocate(tmp_tr(isd:ied,jsd:jed,nz_data)) - call MOM_read_data(filename, potemp_var, tmp_tr(:,:,:), G%Domain) + call MOM_read_data(filename, potemp_var, tmp_tr(:,:,:), G%Domain, scale=US%degC_to_C) call set_up_ALE_sponge_field(tmp_tr, G, GV, tv%T, ALE_CSp) - call MOM_read_data(filename, salin_var, tmp_tr(:,:,:), G%Domain) + call MOM_read_data(filename, salin_var, tmp_tr(:,:,:), G%Domain, scale=US%ppt_to_S) call set_up_ALE_sponge_field(tmp_tr, G, GV, tv%S, ALE_CSp) deallocate(tmp_tr) endif @@ -2120,7 +2125,7 @@ subroutine initialize_sponges_file(G, GV, US, use_temperature, tv, u, v, depth_t call MOM_error(FATAL, " initialize_sponges: Unable to open "//trim(filename)) allocate(tmp_u(G%IsdB:G%IedB,jsd:jed,nz_data)) allocate(tmp_v(isd:ied,G%JsdB:G%JedB,nz_data)) - call MOM_read_vector(filename, u_var, v_var, tmp_u(:,:,:), tmp_v(:,:,:), G%Domain,scale=US%m_s_to_L_T) + call MOM_read_vector(filename, u_var, v_var, tmp_u(:,:,:), tmp_v(:,:,:), G%Domain, scale=US%m_s_to_L_T) call set_up_ALE_sponge_vel_field(tmp_u, tmp_v, G, GV, u, v, ALE_CSp) deallocate(tmp_u,tmp_v) endif @@ -2133,8 +2138,8 @@ subroutine initialize_sponges_file(G, GV, US, use_temperature, tv, u, v, depth_t endif ! The remaining calls to set_up_sponge_field can be in any order. if ( use_temperature) then - call set_up_ALE_sponge_field(filename, potemp_var, Time, G, GV, US, tv%T, ALE_CSp) - call set_up_ALE_sponge_field(filename, salin_var, Time, G, GV, US, tv%S, ALE_CSp) + call set_up_ALE_sponge_field(filename, potemp_var, Time, G, GV, US, tv%T, ALE_CSp, scale=US%C_to_degC) + call set_up_ALE_sponge_field(filename, salin_var, Time, G, GV, US, tv%S, ALE_CSp, scale=US%S_to_ppt) endif if (sponge_uv) then filename = trim(inputdir)//trim(state_uv_file) @@ -2274,10 +2279,10 @@ subroutine initialize_oda_incupd_file(G, GV, US, use_temperature, tv, h, u, v, p if (use_temperature) then allocate(tmp_tr(isd:ied,jsd:jed,nz_data)) ! temperature inc. in array Inc(1) - call MOM_read_data(filename, tempinc_var, tmp_tr(:,:,:), G%Domain) + call MOM_read_data(filename, tempinc_var, tmp_tr(:,:,:), G%Domain, scale=US%degC_to_C) call set_up_oda_incupd_field(tmp_tr, G, GV, oda_incupd_CSp) ! salinity inc. in array Inc(2) - call MOM_read_data(filename, salinc_var, tmp_tr(:,:,:), G%Domain) + call MOM_read_data(filename, salinc_var, tmp_tr(:,:,:), G%Domain, scale=US%ppt_to_S) call set_up_oda_incupd_field(tmp_tr, G, GV, oda_incupd_CSp) deallocate(tmp_tr) endif @@ -2414,7 +2419,8 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just real :: PI_180 ! for conversion from degrees to radians real :: Hmix_default ! The default initial mixed layer depth [m]. real :: Hmix_depth ! The mixed layer depth in the initial condition [Z ~> m]. - real :: missing_value_temp, missing_value_salt + real :: missing_value_temp ! The missing value in the input temperature field + real :: missing_value_salt ! The missing value in the input salinity field logical :: correct_thickness real :: h_tolerance ! A parameter that controls the tolerance when adjusting the ! thickness to fit the bathymetry [Z ~> m]. @@ -2422,15 +2428,15 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just integer, parameter :: niter=10 ! number of iterations for t/s adjustment to layer density logical :: adjust_temperature = .true. ! fit t/s to target densities - real, parameter :: missing_value = -1.e20 - real, parameter :: temp_land_fill = 0.0, salt_land_fill = 35.0 + real :: temp_land_fill ! A temperature value to use for land points [C ~> degC] + real :: salt_land_fill ! A salinity value to use for land points [C ~> degC] logical :: reentrant_x, tripolar_n ! data arrays real, dimension(:), allocatable :: z_edges_in, z_in ! Interface heights [Z ~> m] real, dimension(:), allocatable :: Rb ! Interface densities [R ~> kg m-3] - real, dimension(:,:,:), allocatable, target :: temp_z ! Input temperatures [degC] - real, dimension(:,:,:), allocatable, target :: salt_z ! Input salinities [ppt] + real, dimension(:,:,:), allocatable, target :: temp_z ! Input temperatures [C ~> degC] + real, dimension(:,:,:), allocatable, target :: salt_z ! Input salinities [S ~> ppt] real, dimension(:,:,:), allocatable, target :: mask_z ! 1 for valid data points [nondim] real, dimension(:,:,:), allocatable :: rho_z ! Densities in Z-space [R ~> kg m-3] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: zi ! Interface heights [Z ~> m]. @@ -2441,8 +2447,8 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just ! Local variables for ALE remapping real, dimension(:), allocatable :: hTarget ! Target thicknesses [Z ~> m]. - real, dimension(:,:,:), allocatable, target :: tmpT1dIn ! Input temperatures on a model-sized grid [degC] - real, dimension(:,:,:), allocatable, target :: tmpS1dIn ! Input salinities on a model-sized grid [ppt] + real, dimension(:,:,:), allocatable, target :: tmpT1dIn ! Input temperatures on a model-sized grid [C ~> degC] + real, dimension(:,:,:), allocatable, target :: tmpS1dIn ! Input salinities on a model-sized grid [S ~> ppt] real, dimension(:,:,:), allocatable :: tmp_mask_in ! The valid data mask on a model-sized grid [nondim] real, dimension(:,:,:), allocatable :: h1 ! Thicknesses [H ~> m or kg m-2]. real, dimension(:,:,:), allocatable :: dz_interface ! Change in position of interface due to regridding @@ -2459,8 +2465,8 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just ! from data when finding the initial interface locations in ! layered mode from a dataset of T and S. character(len=64) :: remappingScheme - real :: tempAvg ! Spatially averaged temperatures on a layer [degC] - real :: saltAvg ! Spatially averaged salinities on a layer [ppt] + real :: tempAvg ! Spatially averaged temperatures on a layer [C ~> degC] + real :: saltAvg ! Spatially averaged salinities on a layer [S ~> ppt] logical :: do_conv_adj, ignore integer :: nPoints integer :: id_clock_routine, id_clock_ALE @@ -2587,6 +2593,10 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just return ! All run-time parameters have been read, so return. endif + !### These hard-coded constants should be made into runtime parameters + temp_land_fill = 0.0*US%degC_to_C + salt_land_fill = 35.0*US%ppt_to_S + eps_z = GV%Angstrom_Z eps_rho = 1.0e-10*US%kg_m3_to_R @@ -2605,35 +2615,24 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just ! to the North/South Pole past the limits of the input data, they are extrapolated using the average ! value at the northernmost/southernmost latitude. - call horiz_interp_and_extrap_tracer(tfilename, potemp_var, 1.0, 1, & + call horiz_interp_and_extrap_tracer(tfilename, potemp_var, US%degC_to_C, 1, & G, temp_z, mask_z, z_in, z_edges_in, missing_value_temp, reentrant_x, & - tripolar_n, homogenize, m_to_Z=US%m_to_Z, answers_2018=hor_regrid_answers_2018, ongrid=pre_gridded) + tripolar_n, homogenize, m_to_Z=US%m_to_Z, answers_2018=hor_regrid_answers_2018, & + ongrid=pre_gridded, tr_iter_tol=1.0e-3*US%degC_to_C) - call horiz_interp_and_extrap_tracer(sfilename, salin_var, 1.0, 1, & + call horiz_interp_and_extrap_tracer(sfilename, salin_var, US%ppt_to_S, 1, & G, salt_z, mask_z, z_in, z_edges_in, missing_value_salt, reentrant_x, & - tripolar_n, homogenize, m_to_Z=US%m_to_Z, answers_2018=hor_regrid_answers_2018, ongrid=pre_gridded) + tripolar_n, homogenize, m_to_Z=US%m_to_Z, answers_2018=hor_regrid_answers_2018, & + ongrid=pre_gridded, tr_iter_tol=1.0e-3*US%ppt_to_S) kd = size(z_in,1) ! Convert the sign convention of Z_edges_in. do k=1,size(Z_edges_in,1) ; Z_edges_in(k) = -Z_edges_in(k) ; enddo - allocate(rho_z(isd:ied,jsd:jed,kd)) - ! Convert T&S to Absolute Salinity and Conservative Temperature if using TEOS10 or NEMO call convert_temp_salt_for_TEOS10(temp_z, salt_z, G%HI, kd, mask_z, eos) - press(:) = tv%P_Ref - EOSdom(:) = EOS_domain(G%HI) - do k=1,kd ; do j=js,je - call calculate_density(temp_z(:,j,k), salt_z(:,j,k), press, rho_z(:,j,k), eos, EOSdom) - enddo ; enddo - - call pass_var(temp_z,G%Domain) - call pass_var(salt_z,G%Domain) - call pass_var(mask_z,G%Domain) - call pass_var(rho_z,G%Domain) - do j=js,je ; do i=is,ie Z_bottom(i,j) = -depth_tot(i,j) enddo ; enddo @@ -2663,8 +2662,8 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just tmpT1dIn(i,j,k) = tmpT1dIn(i,j,k-1) tmpS1dIn(i,j,k) = tmpS1dIn(i,j,k-1) else ! This next block should only ever be reached over land - tmpT1dIn(i,j,k) = -99.9 - tmpS1dIn(i,j,k) = -99.9 + tmpT1dIn(i,j,k) = -99.9*US%degC_to_C ! Change to temp_land_fill + tmpS1dIn(i,j,k) = -99.9*US%ppt_to_S ! Change to salt_land_fill endif h1(i,j,k) = GV%Z_to_H * (zTopOfCell - zBottomOfCell) zTopOfCell = zBottomOfCell ! Bottom becomes top for next value of k @@ -2674,9 +2673,6 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just endif ! mask2dT enddo ; enddo deallocate( tmp_mask_in ) - call pass_var(h1, G%Domain) - call pass_var(tmpT1dIn, G%Domain) - call pass_var(tmpS1dIn, G%Domain) ! Build the target grid (and set the model thickness to it) ! This call can be more general but is hard-coded for z* coordinates... ???? @@ -2700,7 +2696,6 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just h(i,j,:) = 0. endif ! mask2dT enddo ; enddo - call pass_var(h, G%Domain) deallocate( hTarget ) endif @@ -2751,9 +2746,18 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just nkml = 0 ; if (separate_mixed_layer) nkml = GV%nkml + press(:) = tv%P_Ref + EOSdom(:) = EOS_domain(G%HI) + allocate(rho_z(isd:ied,jsd:jed,kd)) + do k=1,kd ; do j=js,je + call calculate_density(temp_z(:,j,k), salt_z(:,j,k), press, rho_z(:,j,k), eos, EOSdom) + enddo ; enddo + call find_interfaces(rho_z, z_in, kd, Rb, Z_bottom, zi, G, GV, US, nlevs, nkml, & Hmix_depth, eps_z, eps_rho, density_extrap_bug) + deallocate(rho_z) + if (correct_thickness) then call adjustEtaToFitBathymetry(G, GV, US, zi, h, h_tolerance, dZ_ref_eta=G%Z_ref) else @@ -2779,19 +2783,21 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just endif endif - call tracer_z_init_array(temp_z, z_edges_in, kd, zi, missing_value, G, nz, nlevs, eps_z, tv%T) - call tracer_z_init_array(salt_z, z_edges_in, kd, zi, missing_value, G, nz, nlevs, eps_z, tv%S) - - do k=1,nz - nPoints = 0 ; tempAvg = 0. ; saltAvg = 0. - do j=js,je ; do i=is,ie ; if (G%mask2dT(i,j) > 0.0) then - nPoints = nPoints + 1 - tempAvg = tempAvg + tv%T(i,j,k) - saltAvg = saltAvg + tv%S(i,j,k) - endif ; enddo ; enddo + call tracer_z_init_array(temp_z, z_edges_in, kd, zi, temp_land_fill, G, nz, nlevs, eps_z, & + tv%T) + call tracer_z_init_array(salt_z, z_edges_in, kd, zi, salt_land_fill, G, nz, nlevs, eps_z, & + tv%S) + if (homogenize) then ! Horizontally homogenize data to produce perfectly "flat" initial conditions - if (homogenize) then + do k=1,nz + nPoints = 0 ; tempAvg = 0. ; saltAvg = 0. + do j=js,je ; do i=is,ie ; if (G%mask2dT(i,j) > 0.0) then + nPoints = nPoints + 1 + tempAvg = tempAvg + tv%T(i,j,k) + saltAvg = saltAvg + tv%S(i,j,k) + endif ; enddo ; enddo + !### These averages will not reproduce across PE layouts or grid rotation. call sum_across_PEs(nPoints) call sum_across_PEs(tempAvg) @@ -2802,30 +2808,19 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just endif tv%T(:,:,k) = tempAvg tv%S(:,:,k) = saltAvg - endif - enddo - - endif ! useALEremapping - - ! Fill land values - do k=1,nz ; do j=js,je ; do i=is,ie - if (tv%T(i,j,k) == missing_value) then - tv%T(i,j,k) = temp_land_fill - tv%S(i,j,k) = salt_land_fill + enddo endif - enddo ; enddo ; enddo + if (adjust_temperature) then + ! Finally adjust to target density + ks = 1 ; if (separate_mixed_layer) ks = GV%nk_rho_varies + 1 + call determine_temperature(tv%T, tv%S, GV%Rlay(1:nz), tv%P_Ref, niter, & + h, ks, G, GV, US, eos) + endif - if (adjust_temperature .and. .not. useALEremapping) then - ! Finally adjust to target density - ks = 1 ; if (separate_mixed_layer) ks = GV%nk_rho_varies + 1 - call determine_temperature(tv%T, tv%S, GV%Rlay(1:nz), tv%P_Ref, niter, & - missing_value, h, ks, G, GV, US, eos) - endif + endif ! useALEremapping deallocate(z_in, z_edges_in, temp_z, salt_z, mask_z) - deallocate(rho_z) - call pass_var(h, G%Domain) call pass_var(tv%T, G%Domain) @@ -2976,16 +2971,18 @@ subroutine MOM_state_init_tests(G, GV, US, tv) ! Local variables integer, parameter :: nk=5 - real, dimension(nk) :: T, T_t, T_b ! Temperatures [degC] - real, dimension(nk) :: S, S_t, S_b ! Salinities [ppt] + real, dimension(nk) :: T, T_t, T_b ! Temperatures [C ~> degC] + real, dimension(nk) :: S, S_t, S_b ! Salinities [S ~> ppt] real, dimension(nk) :: rho ! Layer density [R ~> kg m-3] real, dimension(nk) :: h ! Layer thicknesses [H ~> m or kg m-2] real, dimension(nk) :: z ! Height of layer center [Z ~> m] real, dimension(nk+1) :: e ! Interface heights [Z ~> m] - integer :: k + real :: T_ref ! A reference temperature [C ~> degC] + real :: S_ref ! A reference salinity [S ~> ppt] real :: P_tot, P_t, P_b ! Pressures [R L2 T-2 ~> Pa] real :: z_out ! Output height [Z ~> m] real :: I_z_scale ! The inverse of the height scale for prescribed gradients [Z-1 ~> m-1] + integer :: k type(remapping_CS), pointer :: remap_CS => NULL() I_z_scale = 1.0 / (500.0*US%m_to_Z) @@ -2997,14 +2994,16 @@ subroutine MOM_state_init_tests(G, GV, US, tv) e(K+1) = e(K) - GV%H_to_Z * h(k) enddo P_tot = 0. + T_ref = 20.0*US%degC_to_C + S_ref = 35.0*US%ppt_to_S do k = 1, nk z(k) = 0.5 * ( e(K) + e(K+1) ) - T_t(k) = 20. + (0. * I_z_scale) * e(k) - T(k) = 20. + (0. * I_z_scale)*z(k) - T_b(k) = 20. + (0. * I_z_scale)*e(k+1) - S_t(k) = 35. - (0. * I_z_scale)*e(k) - S(k) = 35. + (0. * I_z_scale)*z(k) - S_b(k) = 35. - (0. * I_z_scale)*e(k+1) + T_t(k) = T_ref + (0. * I_z_scale) * e(k) + T(k) = T_ref + (0. * I_z_scale)*z(k) + T_b(k) = T_ref + (0. * I_z_scale)*e(k+1) + S_t(k) = S_ref - (0. * I_z_scale)*e(k) + S(k) = S_ref + (0. * I_z_scale)*z(k) + S_b(k) = S_ref - (0. * I_z_scale)*e(k+1) call calculate_density(0.5*(T_t(k)+T_b(k)), 0.5*(S_t(k)+S_b(k)), -GV%Rho0*GV%g_Earth*z(k), & rho(k), tv%eqn_of_state) P_tot = P_tot + GV%g_Earth * rho(k) * GV%H_to_Z*h(k) diff --git a/src/ocean_data_assim/MOM_oda_driver.F90 b/src/ocean_data_assim/MOM_oda_driver.F90 index a1894eb13f..43a8416a10 100644 --- a/src/ocean_data_assim/MOM_oda_driver.F90 +++ b/src/ocean_data_assim/MOM_oda_driver.F90 @@ -149,11 +149,12 @@ module MOM_oda_driver_mod !> initialize First_guess (prior) and Analysis grid !! information for all ensemble members -subroutine init_oda(Time, G, GV, diag_CS, CS) +subroutine init_oda(Time, G, GV, US, diag_CS, CS) type(time_type), intent(in) :: Time !< The current model time. type(ocean_grid_type), pointer :: G !< domain and grid information for ocean model type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(diag_ctrl), target, intent(inout) :: diag_CS !< A pointer to a diagnostic control structure type(ODA_CS), pointer, intent(inout) :: CS !< The DA control structure @@ -341,9 +342,9 @@ subroutine init_oda(Time, G, GV, diag_CS, CS) ! set up diag variables for analysis increments CS%diag_CS => diag_CS CS%id_inc_t=register_diag_field('ocean_model','temp_increment',diag_CS%axesTL,& - Time,'ocean potential temperature increments','degC') + Time, 'ocean potential temperature increments', 'degC', conversion=US%C_to_degC) CS%id_inc_s=register_diag_field('ocean_model','salt_increment',diag_CS%axesTL,& - Time,'ocean salinity increments','psu') + Time, 'ocean salinity increments', 'psu', conversion=US%S_to_ppt) !! get global grid information from ocean model needed for ODA initialization T_grid=>NULL() @@ -391,7 +392,8 @@ subroutine set_prior_tracer(Time, G, GV, h, tv, CS) type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables type(ODA_CS), pointer :: CS !< ocean DA control structure - real, dimension(SZI_(G),SZJ_(G),CS%nk) :: T, S + real, dimension(SZI_(G),SZJ_(G),CS%nk) :: T ! Temperature on the analysis grid [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),CS%nk) :: S ! Salinity on the analysis grid [S ~> ppt] integer :: i, j, m integer :: isc, iec, jsc, jec real :: h_neglect, h_neglect_edge ! small thicknesses [H ~> m or kg m-2] @@ -478,6 +480,8 @@ subroutine get_posterior_tracer(Time, CS, h, tv, increment) Ocean_increment%T = CS%Ocean_posterior%T - CS%Ocean_prior%T Ocean_increment%S = CS%Ocean_posterior%S - CS%Ocean_prior%S endif + ! It may be necessary to check whether the increment and ocean state have the + ! same dimensionally rescaled units. do m=1,CS%ensemble_size if (get_inc) then call redistribute_array(CS%mpp_domain, Ocean_increment%T(:,:,:,m),& @@ -525,29 +529,31 @@ subroutine oda(Time, CS) !! switch back to ensemble member pelist call set_PElist(CS%ensemble_pelist(CS%ensemble_id,:)) call get_posterior_tracer(Time, CS, increment=.true.) - if (CS%do_bias_adjustment) call get_bias_correction_tracer(Time, CS) + if (CS%do_bias_adjustment) call get_bias_correction_tracer(Time, CS%US, CS) endif return end subroutine oda -subroutine get_bias_correction_tracer(Time, CS) +subroutine get_bias_correction_tracer(Time, US, CS) type(time_type), intent(in) :: Time !< the current model time + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(ODA_CS), pointer :: CS !< ocean DA control structure integer :: i,j,k - real, allocatable, dimension(:,:,:) :: T_bias, S_bias + real, allocatable, dimension(:,:,:) :: T_bias ! Temperature biases [C ~> degC] + real, allocatable, dimension(:,:,:) :: S_bias ! Salinity biases [C ~> degC] real, allocatable, dimension(:,:,:) :: mask_z real, allocatable, dimension(:), target :: z_in, z_edges_in real :: missing_value integer,dimension(3) :: fld_sz call cpu_clock_begin(id_clock_bias_adjustment) - call horiz_interp_and_extrap_tracer(CS%INC_CS%T_id,Time,1.0,CS%G,T_bias,& - mask_z,z_in,z_edges_in,missing_value,.true.,.false.,.false.,.true.) - call horiz_interp_and_extrap_tracer(CS%INC_CS%S_id,Time,1.0,CS%G,S_bias,& - mask_z,z_in,z_edges_in,missing_value,.true.,.false.,.false.,.true.) + call horiz_interp_and_extrap_tracer(CS%INC_CS%T_id, Time, US%degC_to_C, CS%G, T_bias, & + mask_z, z_in, z_edges_in, missing_value, .true., .false., .false., .true.) + call horiz_interp_and_extrap_tracer(CS%INC_CS%S_id, Time, US%ppt_to_S, CS%G, S_bias, & + mask_z, z_in, z_edges_in, missing_value, .true., .false., .false., .true.) ! This should be replaced to use mask_z instead of the following lines ! which are intended to zero land values using an arbitrary limit. @@ -555,8 +561,8 @@ subroutine get_bias_correction_tracer(Time, CS) do i=1,fld_sz(1) do j=1,fld_sz(2) do k=1,fld_sz(3) - if (T_bias(i,j,k) > 1.0E-3) T_bias(i,j,k) = 0.0 - if (S_bias(i,j,k) > 1.0E-3) S_bias(i,j,k) = 0.0 + if (T_bias(i,j,k) > 1.0E-3*US%degC_to_C) T_bias(i,j,k) = 0.0 + if (S_bias(i,j,k) > 1.0E-3*US%ppt_to_S) S_bias(i,j,k) = 0.0 enddo enddo enddo @@ -648,11 +654,11 @@ subroutine apply_oda_tracer_increments(dt, Time_end, G, GV, tv, h, CS) integer :: i, j integer :: isc, iec, jsc, jec real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: T_inc !< an adjustment to the temperature - !! tendency [degC T-1 -> degC s-1] + !! tendency [C T-1 -> degC s-1] real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: S_inc !< an adjustment to the salinity - !! tendency [g kg-1 T-1 -> g kg-1 s-1] - real, dimension(SZI_(G),SZJ_(G),SZK_(CS%Grid)) :: T !< The updated temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(CS%Grid)) :: S !< The updated salinity [g kg-1] + !! tendency [S T-1 -> ppt s-1] + real, dimension(SZI_(G),SZJ_(G),SZK_(CS%Grid)) :: T !< The updated temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(CS%Grid)) :: S !< The updated salinity [S ~> ppt] real :: h_neglect, h_neglect_edge ! small thicknesses [H ~> m or kg m-2] if (.not. associated(CS)) return @@ -690,8 +696,8 @@ subroutine apply_oda_tracer_increments(dt, Time_end, G, GV, tv, h, CS) call pass_var(T_inc, G%Domain) call pass_var(S_inc, G%Domain) - tv%T(isc:iec,jsc:jec,:)=tv%T(isc:iec,jsc:jec,:)+T_inc(isc:iec,jsc:jec,:)*dt - tv%S(isc:iec,jsc:jec,:)=tv%S(isc:iec,jsc:jec,:)+S_inc(isc:iec,jsc:jec,:)*dt + tv%T(isc:iec,jsc:jec,:) = tv%T(isc:iec,jsc:jec,:) + T_inc(isc:iec,jsc:jec,:)*dt + tv%S(isc:iec,jsc:jec,:) = tv%S(isc:iec,jsc:jec,:) + S_inc(isc:iec,jsc:jec,:)*dt call pass_var(tv%T, G%Domain) call pass_var(tv%S, G%Domain) diff --git a/src/ocean_data_assim/MOM_oda_incupd.F90 b/src/ocean_data_assim/MOM_oda_incupd.F90 index 511bd89d7d..77f20c4f66 100644 --- a/src/ocean_data_assim/MOM_oda_incupd.F90 +++ b/src/ocean_data_assim/MOM_oda_incupd.F90 @@ -324,8 +324,10 @@ subroutine calc_oda_increments(h, tv, u, v, G, GV, US, CS) !! that is set by a previous call to initialize_oda_incupd (in). - real, dimension(SZK_(GV)) :: tmp_val1 ! data values on the model grid - real, allocatable, dimension(:) :: tmp_val2 ! data values remapped to increment grid + real, dimension(SZK_(GV)) :: tmp_val1 ! data values on the model grid, in rescaled units + ! like [S ~> ppt] for salinity. + real, allocatable, dimension(:) :: tmp_val2 ! data values remapped to increment grid, in rescaled units + ! like [S ~> ppt] for salinity. real, allocatable, dimension(:,:,:) :: h_obs !< Layer-thicknesses of increments [H ~> m or kg m-2] real, allocatable, dimension(:) :: tmp_h ! temporary array for corrected h_obs [H ~> m or kg m-2] real, allocatable, dimension(:) :: hu_obs ! A column of observation-grid thicknesses at u points [H ~> m or kg m-2] @@ -525,8 +527,8 @@ subroutine apply_oda_incupd(h, tv, u, v, dt, G, GV, US, CS) real, dimension(SZK_(GV)) :: tmp_val1 ! data values remapped to model grid real, dimension(SZK_(GV)) :: hu, hv ! A column of thicknesses at u or v points [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: tmp_t !< A temporary array for t increments [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: tmp_s !< A temporary array for s increments [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: tmp_t !< A temporary array for t increments [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: tmp_s !< A temporary array for s increments [S ~> ppt] real, dimension(SZIB_(G),SZJ_(G),SZK_(GV)) :: tmp_u !< A temporary array for u increments [L T-1 ~> m s-1] real, dimension(SZI_(G),SZJB_(G),SZK_(GV)) :: tmp_v !< A temporary array for v increments [L T-1 ~> m s-1] @@ -724,6 +726,7 @@ subroutine apply_oda_incupd(h, tv, u, v, dt, G, GV, US, CS) if (CS%id_u_oda_inc > 0) call post_data(CS%id_u_oda_inc, tmp_u, CS%diag) if (CS%id_v_oda_inc > 0) call post_data(CS%id_v_oda_inc, tmp_v, CS%diag) endif + !### The argument here seems wrong. if (CS%id_h_oda_inc > 0) call post_data(CS%id_h_oda_inc, h , CS%diag) if (CS%id_T_oda_inc > 0) call post_data(CS%id_T_oda_inc, tmp_t, CS%diag) if (CS%id_S_oda_inc > 0) call post_data(CS%id_S_oda_inc, tmp_s, CS%diag) @@ -764,9 +767,9 @@ subroutine output_oda_incupd_inc(Time, G, GV, param_file, CS, US) ! register the variables to write call register_restart_field(CS%Inc(1)%p, "T_inc", .true., restart_CSp_tmp, & - "Pot. T. increment", "degC") + "Pot. T. increment", "degC", conversion=US%C_to_degC) call register_restart_field(CS%Inc(2)%p, "S_inc", .true., restart_CSp_tmp, & - "Salinity increment", "psu") + "Salinity increment", "psu", conversion=US%S_to_ppt) call register_restart_field(CS%Ref_h%p, "h_obs", .true., restart_CSp_tmp, & "Observational h", units=get_thickness_units(GV), conversion=GV%H_to_MKS) if (CS%uv_inc) then @@ -793,7 +796,7 @@ end subroutine output_oda_incupd_inc subroutine init_oda_incupd_diags(Time, G, GV, diag, CS, US) type(time_type), target, intent(in) :: Time !< The current model time type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure - type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure + type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure type(diag_ctrl), target, intent(inout) :: diag !< A structure that is used to regulate diagnostic !! output. type(oda_incupd_CS), pointer :: CS !< ALE sponge control structure @@ -802,18 +805,17 @@ subroutine init_oda_incupd_diags(Time, G, GV, diag, CS, US) if (.not.associated(CS)) return CS%diag => diag - ! These diagnostics of the state variables increments,useful for debugging the - ! ODA code. + ! These diagnostics of the state variables increments are useful for debugging the ODA code. CS%id_u_oda_inc = register_diag_field('ocean_model', 'u_oda_inc', diag%axesCuL, Time, & - 'Zonal velocity ODA inc.', 'm s-1') + 'Zonal velocity ODA inc.', 'm s-1', conversion=US%L_T_to_m_s) CS%id_v_oda_inc = register_diag_field('ocean_model', 'v_oda_inc', diag%axesCvL, Time, & - 'Meridional velocity ODA inc.', 'm s-1') + 'Meridional velocity ODA inc.', 'm s-1', conversion=US%L_T_to_m_s) CS%id_h_oda_inc = register_diag_field('ocean_model', 'h_oda_inc', diag%axesTL, Time, & - 'Layer Thickness ODA inc.', get_thickness_units(GV)) + 'Layer Thickness ODA inc.', get_thickness_units(GV), conversion=GV%H_to_mks) CS%id_T_oda_inc = register_diag_field('ocean_model', 'T_oda_inc', diag%axesTL, Time, & - 'Temperature ODA inc.', 'degC') + 'Temperature ODA inc.', 'degC', conversion=US%C_to_degC) CS%id_S_oda_inc = register_diag_field('ocean_model', 'S_oda_inc', diag%axesTL, Time, & - 'Salinity ODA inc.', 'PSU') + 'Salinity ODA inc.', 'PSU', conversion=US%S_to_ppt) end subroutine init_oda_incupd_diags diff --git a/src/parameterizations/lateral/MOM_thickness_diffuse.F90 b/src/parameterizations/lateral/MOM_thickness_diffuse.F90 index 036337a8de..4ab0c0cf3d 100644 --- a/src/parameterizations/lateral/MOM_thickness_diffuse.F90 +++ b/src/parameterizations/lateral/MOM_thickness_diffuse.F90 @@ -440,8 +440,8 @@ subroutine thickness_diffuse(h, uhtr, vhtr, tv, dt, G, GV, US, MEKE, VarMix, CDp G%HI, haloshift=0, scale=US%Z_to_L) endif if (associated(tv%eqn_of_state)) then - call hchksum(tv%T, "thickness_diffuse T", G%HI, haloshift=1) - call hchksum(tv%S, "thickness_diffuse S", G%HI, haloshift=1) + call hchksum(tv%T, "thickness_diffuse T", G%HI, haloshift=1, scale=US%C_to_degC) + call hchksum(tv%S, "thickness_diffuse S", G%HI, haloshift=1, scale=US%S_to_ppt) endif endif @@ -594,9 +594,9 @@ subroutine thickness_diffuse_full(h, e, Kh_u, Kh_v, tv, uhD, vhD, cg1, dt, G, GV ! Local variables real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: & - T, & ! The temperature [degC], with the values in + T, & ! The temperature [C ~> degC], with the values in ! in massless layers filled vertically by diffusion. - S, & ! The filled salinity [ppt], with the values in + S, & ! The filled salinity [S ~> ppt], with the values in ! in massless layers filled vertically by diffusion. h_avail, & ! The mass available for diffusion out of each face, divided ! by dt [H L2 T-1 ~> m3 s-1 or kg s-1]. @@ -614,23 +614,23 @@ subroutine thickness_diffuse_full(h, e, Kh_u, Kh_v, tv, uhD, vhD, cg1, dt, G, GV pres, & ! The pressure at an interface [R L2 T-2 ~> Pa]. h_avail_rsum ! The running sum of h_avail above an interface [H L2 T-1 ~> m3 s-1 or kg s-1]. real, dimension(SZIB_(G)) :: & - drho_dT_u, & ! The derivative of density with temperature at u points [R degC-1 ~> kg m-3 degC-1] - drho_dS_u, & ! The derivative of density with salinity at u points [R ppt-1 ~> kg m-3 ppt-1]. - drho_dT_dT_u ! The second derivative of density with temperature at u points [R degC-2 ~> kg m-3 degC-2] + drho_dT_u, & ! The derivative of density with temperature at u points [R C-1 ~> kg m-3 degC-1] + drho_dS_u, & ! The derivative of density with salinity at u points [R S-1 ~> kg m-3 ppt-1]. + drho_dT_dT_u ! The second derivative of density with temperature at u points [R C-2 ~> kg m-3 degC-2] real, dimension(SZIB_(G)) :: scrap ! An array to pass to calculate_density_second_derivs() that will be ignored. real, dimension(SZI_(G)) :: & - drho_dT_v, & ! The derivative of density with temperature at v points [R degC-1 ~> kg m-3 degC-1] - drho_dS_v, & ! The derivative of density with salinity at v points [R ppt-1 ~> kg m-3 ppt-1]. - drho_dT_dT_v ! The second derivative of density with temperature at v points [R degC-2 ~> kg m-3 degC-2] + drho_dT_v, & ! The derivative of density with temperature at v points [R C-1 ~> kg m-3 degC-1] + drho_dS_v, & ! The derivative of density with salinity at v points [R S-1 ~> kg m-3 ppt-1]. + drho_dT_dT_v ! The second derivative of density with temperature at v points [R C-2 ~> kg m-3 degC-2] real :: uhtot(SZIB_(G),SZJ_(G)) ! The vertical sum of uhD [H L2 T-1 ~> m3 s-1 or kg s-1]. real :: vhtot(SZI_(G),SZJB_(G)) ! The vertical sum of vhD [H L2 T-1 ~> m3 s-1 or kg s-1]. real, dimension(SZIB_(G)) :: & - T_u, & ! Temperature on the interface at the u-point [degC]. - S_u, & ! Salinity on the interface at the u-point [ppt]. + T_u, & ! Temperature on the interface at the u-point [C ~> degC]. + S_u, & ! Salinity on the interface at the u-point [S ~> ppt]. pres_u ! Pressure on the interface at the u-point [R L2 T-2 ~> Pa]. real, dimension(SZI_(G)) :: & - T_v, & ! Temperature on the interface at the v-point [degC]. - S_v, & ! Salinity on the interface at the v-point [ppt]. + T_v, & ! Temperature on the interface at the v-point [C ~> degC]. + S_v, & ! Salinity on the interface at the v-point [S ~> ppt]. pres_v ! Pressure on the interface at the v-point [R L2 T-2 ~> Pa]. real :: Work_u(SZIB_(G),SZJ_(G)) ! The work being done by the thickness real :: Work_v(SZI_(G),SZJB_(G)) ! diffusion integrated over a cell [R Z L4 T-3 ~> W] @@ -687,12 +687,12 @@ subroutine thickness_diffuse_full(h, e, Kh_u, Kh_v, tv, uhD, vhD, cg1, dt, G, GV real :: G_rho0 ! g/Rho0 [L2 R-1 Z-1 T-2 ~> m4 kg-1 s-2]. real :: N2_floor ! A floor for N2 to avoid degeneracy in the elliptic solver ! times unit conversion factors [T-2 L2 Z-2 ~> s-2] - real :: Tl(5) ! copy of T in local stencil [degC] - real :: mn_T ! mean of T in local stencil [degC] - real :: mn_T2 ! mean of T**2 in local stencil [degC2] + real :: Tl(5) ! copy of T in local stencil [C ~> degC] + real :: mn_T ! mean of T in local stencil [C ~> degC] + real :: mn_T2 ! mean of T**2 in local stencil [C2 ~> degC2] real :: hl(5) ! Copy of local stencil of H [H ~> m] real :: r_sm_H ! Reciprocal of sum of H in local stencil [H-1 ~> m-1] - real :: Tsgs2(SZI_(G),SZJ_(G),SZK_(GV)) ! Sub-grid temperature variance [degC2] + real :: Tsgs2(SZI_(G),SZJ_(G),SZK_(GV)) ! Sub-grid temperature variance [C2 ~> degC2] real :: diag_sfn_x(SZIB_(G),SZJ_(G),SZK_(GV)+1) ! Diagnostic of the x-face streamfunction ! [H L2 T-1 ~> m3 s-1 or kg s-1] @@ -761,11 +761,11 @@ subroutine thickness_diffuse_full(h, e, Kh_u, Kh_v, tv, uhD, vhD, cg1, dt, G, GV if (use_Stanley) then !$OMP do do k=1, nz ; do j=js-1,je+1 ; do i=is-1,ie+1 - !! SGS variance in i-direction [degC2] + !! SGS variance in i-direction [C2 ~> degC2] !dTdi2 = ( ( G%mask2dCu(I ,j) * G%IdxCu(I ,j) * ( T(i+1,j,k) - T(i,j,k) ) & ! + G%mask2dCu(I-1,j) * G%IdxCu(I-1,j) * ( T(i,j,k) - T(i-1,j,k) ) & ! ) * G%dxT(i,j) * 0.5 )**2 - !! SGS variance in j-direction [degC2] + !! SGS variance in j-direction [C2 ~> degC2] !dTdj2 = ( ( G%mask2dCv(i,J ) * G%IdyCv(i,J ) * ( T(i,j+1,k) - T(i,j,k) ) & ! + G%mask2dCv(i,J-1) * G%IdyCv(i,J-1) * ( T(i,j,k) - T(i,j-1,k) ) & ! ) * G%dyT(i,j) * 0.5 )**2 diff --git a/src/parameterizations/vertical/MOM_ALE_sponge.F90 b/src/parameterizations/vertical/MOM_ALE_sponge.F90 index 7be84d2522..9409a07fc1 100644 --- a/src/parameterizations/vertical/MOM_ALE_sponge.F90 +++ b/src/parameterizations/vertical/MOM_ALE_sponge.F90 @@ -78,6 +78,7 @@ module MOM_ALE_sponge integer :: id !< id for FMS external time interpolator integer :: nz_data !< The number of vertical levels in the input field integer :: num_tlevs !< The number of time records contained in the file + real :: scale = 1.0 !< A multiplicative factor by which to rescale input data real, dimension(:,:), pointer :: p => NULL() !< pointer the data. real, dimension(:,:), pointer :: h => NULL() !< pointer the data grid. end type p2d @@ -617,7 +618,7 @@ end subroutine init_ALE_sponge_diags !> This subroutine stores the reference profile at h points for the variable !! whose address is given by f_ptr. -subroutine set_up_ALE_sponge_field_fixed(sp_val, G, GV, f_ptr, CS) +subroutine set_up_ALE_sponge_field_fixed(sp_val, G, GV, f_ptr, CS, scale) type(ocean_grid_type), intent(in) :: G !< Grid structure type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure type(ALE_sponge_CS), pointer :: CS !< ALE sponge control structure (in/out). @@ -626,12 +627,17 @@ subroutine set_up_ALE_sponge_field_fixed(sp_val, G, GV, f_ptr, CS) !! arbitrary number of layers. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & target, intent(in) :: f_ptr !< Pointer to the field to be damped + real, optional, intent(in) :: scale !< A factor by which to rescale the input data, including any + !! contributions due to dimensional rescaling. The default is 1. + real :: scale_fac ! A factor by which to scale sp_val before storing it. integer :: k, col character(len=256) :: mesg ! String for error messages if (.not.associated(CS)) return + scale_fac = 1.0 ; if (present(scale)) scale_fac = scale + CS%fldno = CS%fldno + 1 if (CS%fldno > MAX_FIELDS_) then write(mesg,'("Increase MAX_FIELDS_ to at least ",I3," in MOM_memory.h or decrease & @@ -645,7 +651,7 @@ subroutine set_up_ALE_sponge_field_fixed(sp_val, G, GV, f_ptr, CS) allocate(CS%Ref_val(CS%fldno)%p(CS%nz_data,CS%num_col), source=0.0) do col=1,CS%num_col do k=1,CS%nz_data - CS%Ref_val(CS%fldno)%p(k,col) = sp_val(CS%col_i(col),CS%col_j(col),k) + CS%Ref_val(CS%fldno)%p(k,col) = scale_fac*sp_val(CS%col_i(col),CS%col_j(col),k) enddo enddo @@ -655,7 +661,7 @@ end subroutine set_up_ALE_sponge_field_fixed !> This subroutine stores the reference profile at h points for the variable !! whose address is given by filename and fieldname. -subroutine set_up_ALE_sponge_field_varying(filename, fieldname, Time, G, GV, US, f_ptr, CS) +subroutine set_up_ALE_sponge_field_varying(filename, fieldname, Time, G, GV, US, f_ptr, CS, scale) character(len=*), intent(in) :: filename !< The name of the file with the !! time varying field data character(len=*), intent(in) :: fieldname !< The name of the field in the file @@ -667,6 +673,8 @@ subroutine set_up_ALE_sponge_field_varying(filename, fieldname, Time, G, GV, US, real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & target, intent(in) :: f_ptr !< Pointer to the field to be damped (in). type(ALE_sponge_CS), pointer :: CS !< Sponge control structure (in/out). + real, optional, intent(in) :: scale !< A factor by which to rescale the input data, including any + !! contributions due to dimensional rescaling. The default is 1. ! Local variables integer :: isd, ied, jsd, jed @@ -697,6 +705,7 @@ subroutine set_up_ALE_sponge_field_varying(filename, fieldname, Time, G, GV, US, nz_data = fld_sz(3) CS%Ref_val(CS%fldno)%nz_data = nz_data !< individual sponge fields may reside on a different vertical grid CS%Ref_val(CS%fldno)%num_tlevs = fld_sz(4) + CS%Ref_val(CS%fldno)%scale = 1.0 ; if (present(scale)) CS%Ref_val(CS%fldno)%scale = scale ! initializes the target profile array for this field ! for all columns which will be masked allocate(CS%Ref_val(CS%fldno)%p(nz_data,CS%num_col), source=0.0) @@ -707,7 +716,7 @@ end subroutine set_up_ALE_sponge_field_varying !> This subroutine stores the reference profile at u and v points for the variable !! whose address is given by u_ptr and v_ptr. -subroutine set_up_ALE_sponge_vel_field_fixed(u_val, v_val, G, GV, u_ptr, v_ptr, CS) +subroutine set_up_ALE_sponge_vel_field_fixed(u_val, v_val, G, GV, u_ptr, v_ptr, CS, scale) type(ocean_grid_type), intent(in) :: G !< Grid structure (in). type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure type(ALE_sponge_CS), pointer :: CS !< Sponge structure (in/out). @@ -721,23 +730,28 @@ subroutine set_up_ALE_sponge_vel_field_fixed(u_val, v_val, G, GV, u_ptr, v_ptr, !! have fewer layers than the model itself, but not more. real, target, dimension(SZIB_(G),SZJ_(G),SZK_(GV)), intent(in) :: u_ptr !< u-field to be damped [L T-1 ~> m s-1] real, target, dimension(SZI_(G),SZJB_(G),SZK_(GV)), intent(in) :: v_ptr !< v-field to be damped [L T-1 ~> m s-1] + real, optional, intent(in) :: scale !< A factor by which to rescale the input data, including any + !! contributions due to dimensional rescaling. The default is 1. + real :: scale_fac integer :: k, col if (.not.associated(CS)) return + scale_fac = 1.0 ; if (present(scale)) scale_fac = scale + ! stores the reference profile allocate(CS%Ref_val_u%p(CS%nz_data,CS%num_col_u), source=0.0) do col=1,CS%num_col_u do k=1,CS%nz_data - CS%Ref_val_u%p(k,col) = u_val(CS%col_i_u(col),CS%col_j_u(col),k) + CS%Ref_val_u%p(k,col) = scale_fac*u_val(CS%col_i_u(col),CS%col_j_u(col),k) enddo enddo CS%var_u%p => u_ptr allocate(CS%Ref_val_v%p(CS%nz_data,CS%num_col_v), source=0.0) do col=1,CS%num_col_v do k=1,CS%nz_data - CS%Ref_val_v%p(k,col) = v_val(CS%col_i_v(col),CS%col_j_v(col),k) + CS%Ref_val_v%p(k,col) = scale_fac*v_val(CS%col_i_v(col),CS%col_j_v(col),k) enddo enddo CS%var_v%p => v_ptr @@ -747,7 +761,7 @@ end subroutine set_up_ALE_sponge_vel_field_fixed !> This subroutine stores the reference profile at u and v points for the variable !! whose address is given by u_ptr and v_ptr. subroutine set_up_ALE_sponge_vel_field_varying(filename_u, fieldname_u, filename_v, fieldname_v, & - Time, G, GV, US, CS, u_ptr, v_ptr) + Time, G, GV, US, CS, u_ptr, v_ptr, scale) character(len=*), intent(in) :: filename_u !< File name for u field character(len=*), intent(in) :: fieldname_u !< Name of u variable in file character(len=*), intent(in) :: filename_v !< File name for v field @@ -759,6 +773,9 @@ subroutine set_up_ALE_sponge_vel_field_varying(filename_u, fieldname_u, filename type(ALE_sponge_CS), pointer :: CS !< Sponge structure (in/out). real, target, dimension(SZIB_(G),SZJ_(G),SZK_(GV)), intent(in) :: u_ptr !< u-field to be damped [L T-1 ~> m s-1] real, target, dimension(SZI_(G),SZJB_(G),SZK_(GV)), intent(in) :: v_ptr !< v-field to be damped [L T-1 ~> m s-1] + real, optional, intent(in) :: scale !< A factor by which to rescale the input data, including any + !! contributions due to dimensional rescaling. For varying + !! velocities the default is the same using US%m_s_to_L_T. ! Local variables logical :: override @@ -783,6 +800,7 @@ subroutine set_up_ALE_sponge_vel_field_varying(filename_u, fieldname_u, filename call get_external_field_info(CS%Ref_val_u%id, size=fld_sz) CS%Ref_val_u%nz_data = fld_sz(3) CS%Ref_val_u%num_tlevs = fld_sz(4) + CS%Ref_val_u%scale = US%m_s_to_L_T ; if (present(scale)) CS%Ref_val_u%scale = scale if (CS%spongeDataOngrid) then CS%Ref_val_v%id = init_external_field(filename_v, fieldname_v, domain=G%Domain%mpp_domain) @@ -793,6 +811,7 @@ subroutine set_up_ALE_sponge_vel_field_varying(filename_u, fieldname_u, filename call get_external_field_info(CS%Ref_val_v%id, size=fld_sz) CS%Ref_val_v%nz_data = fld_sz(3) CS%Ref_val_v%num_tlevs = fld_sz(4) + CS%Ref_val_v%scale = US%m_s_to_L_T ; if (present(scale)) CS%Ref_val_v%scale = scale ! stores the reference profile allocate(CS%Ref_val_u%p(fld_sz(3),CS%num_col_u), source=0.0) @@ -860,8 +879,8 @@ subroutine apply_ALE_sponge(h, dt, G, GV, US, CS, Time) if (CS%time_varying_sponges) then do m=1,CS%fldno nz_data = CS%Ref_val(m)%nz_data - call horiz_interp_and_extrap_tracer(CS%Ref_val(m)%id, Time, 1.0, G, sp_val, mask_z, z_in, & - z_edges_in, missing_value, CS%reentrant_x, CS%tripolar_N, .false., & + call horiz_interp_and_extrap_tracer(CS%Ref_val(m)%id, Time, CS%Ref_val(m)%scale, G, sp_val, & + mask_z, z_in, z_edges_in, missing_value, CS%reentrant_x, CS%tripolar_N, .false., & spongeOnGrid=CS%SpongeDataOngrid, m_to_Z=US%m_to_Z, & answers_2018=CS%hor_regrid_answers_2018) allocate( hsrc(nz_data) ) @@ -944,10 +963,10 @@ subroutine apply_ALE_sponge(h, dt, G, GV, US, CS, Time) if (CS%time_varying_sponges) then nz_data = CS%Ref_val_u%nz_data ! Interpolate from the external horizontal grid and in time - call horiz_interp_and_extrap_tracer(CS%Ref_val_u%id, Time, US%m_s_to_L_T, G, sp_val, mask_z, z_in, & - z_edges_in, missing_value, CS%reentrant_x, CS%tripolar_N, .false., & - spongeOnGrid=CS%SpongeDataOngrid, m_to_Z=US%m_to_Z,& - answers_2018=CS%hor_regrid_answers_2018) + call horiz_interp_and_extrap_tracer(CS%Ref_val_u%id, Time, CS%Ref_val_u%scale, G, sp_val, & + mask_z, z_in, z_edges_in, missing_value, CS%reentrant_x, CS%tripolar_N, .false., & + spongeOnGrid=CS%SpongeDataOngrid, m_to_Z=US%m_to_Z,& + answers_2018=CS%hor_regrid_answers_2018) ! Initialize mask_z halos to zero before pass_var, in case of no update mask_z(G%isc-1, G%jsc:G%jec, :) = 0. @@ -993,10 +1012,10 @@ subroutine apply_ALE_sponge(h, dt, G, GV, US, CS, Time) deallocate(sp_val, mask_u, mask_z, hsrc) nz_data = CS%Ref_val_v%nz_data ! Interpolate from the external horizontal grid and in time - call horiz_interp_and_extrap_tracer(CS%Ref_val_v%id, Time, US%m_s_to_L_T, G, sp_val, mask_z, z_in, & - z_edges_in, missing_value, CS%reentrant_x, CS%tripolar_N, .false., & - spongeOnGrid=CS%SpongeDataOngrid, m_to_Z=US%m_to_Z,& - answers_2018=CS%hor_regrid_answers_2018) + call horiz_interp_and_extrap_tracer(CS%Ref_val_v%id, Time, CS%Ref_val_v%scale, G, sp_val, & + mask_z, z_in, z_edges_in, missing_value, CS%reentrant_x, CS%tripolar_N, .false., & + spongeOnGrid=CS%SpongeDataOngrid, m_to_Z=US%m_to_Z,& + answers_2018=CS%hor_regrid_answers_2018) ! Initialize mask_z halos to zero before pass_var, in case of no update mask_z(G%isc:G%iec, G%jsc-1, :) = 0. mask_z(G%isc:G%iec, G%jec+1, :) = 0. diff --git a/src/parameterizations/vertical/MOM_CVMix_KPP.F90 b/src/parameterizations/vertical/MOM_CVMix_KPP.F90 index 30818a6f1f..aa9468b67f 100644 --- a/src/parameterizations/vertical/MOM_CVMix_KPP.F90 +++ b/src/parameterizations/vertical/MOM_CVMix_KPP.F90 @@ -162,8 +162,8 @@ module MOM_CVMix_KPP real, allocatable, dimension(:,:,:) :: Kt_KPP !< Temp diffusivity from KPP [m2 s-1] real, allocatable, dimension(:,:,:) :: Ks_KPP !< Scalar diffusivity from KPP [m2 s-1] real, allocatable, dimension(:,:,:) :: Kv_KPP !< Viscosity due to KPP [m2 s-1] - real, allocatable, dimension(:,:) :: Tsurf !< Temperature of surface layer [degC] - real, allocatable, dimension(:,:) :: Ssurf !< Salinity of surface layer [ppt] + real, allocatable, dimension(:,:) :: Tsurf !< Temperature of surface layer [C ~> degC] + real, allocatable, dimension(:,:) :: Ssurf !< Salinity of surface layer [S ~> ppt] real, allocatable, dimension(:,:) :: Usurf !< i-velocity of surface layer [m s-1] real, allocatable, dimension(:,:) :: Vsurf !< j-velocity of surface layer [m s-1] real, allocatable, dimension(:,:,:) :: EnhK !< Enhancement for mixing coefficient @@ -535,11 +535,14 @@ logical function KPP_init(paramFile, G, GV, US, diag, Time, CS, passive) CS%id_uStar = register_diag_field('ocean_model', 'KPP_uStar', diag%axesT1, Time, & 'Friction velocity, u*, as used by [CVMix] KPP', 'm/s', conversion=US%Z_to_m*US%s_to_T) CS%id_buoyFlux = register_diag_field('ocean_model', 'KPP_buoyFlux', diag%axesTi, Time, & - 'Surface (and penetrating) buoyancy flux, as used by [CVMix] KPP', 'm2/s3', conversion=US%L_to_m**2*US%s_to_T**3) + 'Surface (and penetrating) buoyancy flux, as used by [CVMix] KPP', & + 'm2/s3', conversion=US%L_to_m**2*US%s_to_T**3) CS%id_QminusSW = register_diag_field('ocean_model', 'KPP_QminusSW', diag%axesT1, Time, & - 'Net temperature flux ignoring short-wave, as used by [CVMix] KPP', 'K m/s', conversion=GV%H_to_m*US%s_to_T) + 'Net temperature flux ignoring short-wave, as used by [CVMix] KPP', & + 'K m/s', conversion=US%C_to_degC*GV%H_to_m*US%s_to_T) CS%id_netS = register_diag_field('ocean_model', 'KPP_netSalt', diag%axesT1, Time, & - 'Effective net surface salt flux, as used by [CVMix] KPP', 'ppt m/s', conversion=GV%H_to_m*US%s_to_T) + 'Effective net surface salt flux, as used by [CVMix] KPP', & + 'ppt m/s', conversion=US%S_to_ppt*GV%H_to_m*US%s_to_T) CS%id_Kt_KPP = register_diag_field('ocean_model', 'KPP_Kheat', diag%axesTi, Time, & 'Heat diffusivity due to KPP, as calculated by [CVMix] KPP', 'm2/s') CS%id_Kd_in = register_diag_field('ocean_model', 'KPP_Kd_in', diag%axesTi, Time, & @@ -554,20 +557,20 @@ logical function KPP_init(paramFile, G, GV, US, diag, Time, CS, passive) 'Non-local tranpsort (Cs*G(sigma)) for scalars, as calculated by [CVMix] KPP', 'nondim') CS%id_NLT_dTdt = register_diag_field('ocean_model', 'KPP_NLT_dTdt', diag%axesTL, Time, & 'Temperature tendency due to non-local transport of heat, as calculated by [CVMix] KPP', & - 'K/s', conversion=US%s_to_T) + 'K/s', conversion=US%C_to_degC*US%s_to_T) CS%id_NLT_dSdt = register_diag_field('ocean_model', 'KPP_NLT_dSdt', diag%axesTL, Time, & 'Salinity tendency due to non-local transport of salt, as calculated by [CVMix] KPP', & - 'ppt/s', conversion=US%s_to_T) + 'ppt/s', conversion=US%S_to_ppt*US%s_to_T) CS%id_NLT_temp_budget = register_diag_field('ocean_model', 'KPP_NLT_temp_budget', diag%axesTL, Time, & 'Heat content change due to non-local transport, as calculated by [CVMix] KPP', & 'W/m^2', conversion=US%QRZ_T_to_W_m2) CS%id_NLT_saln_budget = register_diag_field('ocean_model', 'KPP_NLT_saln_budget', diag%axesTL, Time, & 'Salt content change due to non-local transport, as calculated by [CVMix] KPP', & - 'kg/(sec*m^2)', conversion=US%RZ_T_to_kg_m2s) + 'kg/(sec*m^2)', conversion=US%S_to_ppt*US%RZ_T_to_kg_m2s) !### Should be multiplied by 1000? CS%id_Tsurf = register_diag_field('ocean_model', 'KPP_Tsurf', diag%axesT1, Time, & - 'Temperature of surface layer (10% of OBL depth) as passed to [CVMix] KPP', 'C') + 'Temperature of surface layer (10% of OBL depth) as passed to [CVMix] KPP', 'C', conversion=US%C_to_degC) CS%id_Ssurf = register_diag_field('ocean_model', 'KPP_Ssurf', diag%axesT1, Time, & - 'Salinity of surface layer (10% of OBL depth) as passed to [CVMix] KPP', 'ppt') + 'Salinity of surface layer (10% of OBL depth) as passed to [CVMix] KPP', 'ppt', conversion=US%S_to_ppt) CS%id_Usurf = register_diag_field('ocean_model', 'KPP_Usurf', diag%axesCu1, Time, & 'i-component flow of surface layer (10% of OBL depth) as passed to [CVMix] KPP', 'm/s') CS%id_Vsurf = register_diag_field('ocean_model', 'KPP_Vsurf', diag%axesCv1, Time, & @@ -916,8 +919,8 @@ subroutine KPP_compute_BLD(CS, G, GV, US, h, Temp, Salt, u, v, tv, uStar, buoyFl type(verticalGrid_type), intent(in) :: GV !< Ocean vertical grid type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer/level thicknesses [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Temp !< potential/cons temp [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Salt !< Salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Temp !< potential/cons temp [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: Salt !< Salinity [S ~> ppt] real, dimension(SZIB_(G),SZJ_(G),SZK_(GV)), intent(in) :: u !< Velocity i-component [L T-1 ~> m s-1] real, dimension(SZI_(G),SZJB_(G),SZK_(GV)), intent(in) :: v !< Velocity j-component [L T-1 ~> m s-1] type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamics structure. @@ -940,8 +943,8 @@ subroutine KPP_compute_BLD(CS, G, GV, US, h, Temp, Salt, u, v, tv, uStar, buoyFl ! for EOS calculation real, dimension( 3*GV%ke ) :: rho_1D ! A column of densities [R ~> kg m-3] real, dimension( 3*GV%ke ) :: pres_1D ! A column of pressures [R L2 T-2 ~> Pa] - real, dimension( 3*GV%ke ) :: Temp_1D ! A column of temperatures [degC] - real, dimension( 3*GV%ke ) :: Salt_1D ! A column of salinities [ppt] + real, dimension( 3*GV%ke ) :: Temp_1D ! A column of temperatures [C ~> degC] + real, dimension( 3*GV%ke ) :: Salt_1D ! A column of salinities [S ~> ppt] real :: surfFricVel, surfBuoyFlux, Coriolis real :: GoRho ! Gravitational acceleration divided by density in MKS units [m R-1 s-2 ~> m4 kg-1 s-2] @@ -953,8 +956,8 @@ subroutine KPP_compute_BLD(CS, G, GV, US, h, Temp, Salt, u, v, tv, uStar, buoyFl real :: hTot ! Running sum of thickness used in the surface layer average [m] real :: buoy_scale ! A unit conversion factor for buoyancy fluxes [m2 T3 L-2 s-3 ~> 1] real :: delH ! Thickness of a layer [m] - real :: surfHtemp, surfTemp ! Integral and average of temp over the surface layer - real :: surfHsalt, surfSalt ! Integral and average of saln over the surface layer + real :: surfHtemp, surfTemp ! Integral and average of temp over the surface layer [C ~> degC] + real :: surfHsalt, surfSalt ! Integral and average of saln over the surface layer [S ~> ppt] real :: surfHu, surfU ! Integral and average of u over the surface layer real :: surfHv, surfV ! Integral and average of v over the surface layer real :: dh ! The local thickness used for calculating interface positions [m] @@ -971,8 +974,8 @@ subroutine KPP_compute_BLD(CS, G, GV, US, h, Temp, Salt, u, v, tv, uStar, buoyFl "KPP_compute_BLD: The Waves control structure must be associated if STOKES_MIXING is True.") if (CS%debug) then - call hchksum(Salt, "KPP in: S",G%HI,haloshift=0) - call hchksum(Temp, "KPP in: T",G%HI,haloshift=0) + call hchksum(Salt, "KPP in: S", G%HI, haloshift=0, scale=US%S_to_ppt) + call hchksum(Temp, "KPP in: T", G%HI, haloshift=0, scale=US%C_to_degC) call hchksum(u, "KPP in: u",G%HI,haloshift=0,scale=US%L_T_to_m_s) call hchksum(v, "KPP in: v",G%HI,haloshift=0,scale=US%L_T_to_m_s) endif @@ -1389,14 +1392,14 @@ subroutine KPP_NonLocalTransport_temp(CS, G, GV, h, nonLocalTrans, surfFlux, & real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer/level thickness [H ~> m or kg m-2] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), intent(in) :: nonLocalTrans !< Non-local transport [nondim] real, dimension(SZI_(G),SZJ_(G)), intent(in) :: surfFlux !< Surface flux of temperature - !! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] + !! [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] real, intent(in) :: dt !< Time-step [T ~> s] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: scalar !< temperature [degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: scalar !< temperature [C ~> degC] real, intent(in) :: C_p !< Seawater specific heat capacity - !! [Q degC-1 ~> J kg-1 degC-1] + !! [Q C-1 ~> J kg-1 degC-1] integer :: i, j, k - real, dimension( SZI_(G), SZJ_(G),SZK_(GV) ) :: dtracer ! Rate of tracer change [degC T-1 ~> degC s-1] + real, dimension( SZI_(G), SZJ_(G),SZK_(GV) ) :: dtracer ! Rate of tracer change [C T-1 ~> degC s-1] dtracer(:,:,:) = 0.0 @@ -1453,12 +1456,12 @@ subroutine KPP_NonLocalTransport_saln(CS, G, GV, h, nonLocalTrans, surfFlux, dt, real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer/level thickness [H ~> m or kg m-2] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), intent(in) :: nonLocalTrans !< Non-local transport [nondim] real, dimension(SZI_(G),SZJ_(G)), intent(in) :: surfFlux !< Surface flux of salt - !! [ppt H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] + !! [S H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] real, intent(in) :: dt !< Time-step [T ~> s] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: scalar !< Salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: scalar !< Salinity [S ~> ppt] integer :: i, j, k - real, dimension( SZI_(G), SZJ_(G),SZK_(GV) ) :: dtracer ! Rate of tracer change [ppt T-1 ~> ppt s-1] + real, dimension( SZI_(G), SZJ_(G),SZK_(GV) ) :: dtracer ! Rate of tracer change [S T-1 ~> ppt s-1] dtracer(:,:,:) = 0.0 @@ -1493,7 +1496,7 @@ subroutine KPP_NonLocalTransport_saln(CS, G, GV, h, nonLocalTrans, surfFlux, dt, do k = 1, GV%ke do j = G%jsc, G%jec do i = G%isc, G%iec - ! Here dtracer has units of [ppt R Z T-1 ~> ppt kg m-2 s-1] + ! Here dtracer has units of [S R Z T-1 ~> ppt kg m-2 s-1] dtracer(i,j,k) = (nonLocalTrans(i,j,k) - nonLocalTrans(i,j,k+1)) * & surfFlux(i,j) * GV%H_to_RZ enddo diff --git a/src/parameterizations/vertical/MOM_CVMix_ddiff.F90 b/src/parameterizations/vertical/MOM_CVMix_ddiff.F90 index b77387f521..413b87f631 100644 --- a/src/parameterizations/vertical/MOM_CVMix_ddiff.F90 +++ b/src/parameterizations/vertical/MOM_CVMix_ddiff.F90 @@ -160,15 +160,15 @@ subroutine compute_ddiff_coeffs(h, tv, G, GV, US, j, Kd_T, Kd_S, CS, R_rho) ! Local variables real, dimension(SZK_(GV)) :: & cellHeight, & !< Height of cell centers [m] - dRho_dT, & !< partial derivatives of density wrt temp [R degC-1 ~> kg m-3 degC-1] - dRho_dS, & !< partial derivatives of density wrt saln [R ppt-1 ~> kg m-3 ppt-1] + dRho_dT, & !< partial derivatives of density wrt temp [R C-1 ~> kg m-3 degC-1] + dRho_dS, & !< partial derivatives of density wrt saln [R S-1 ~> kg m-3 ppt-1] pres_int, & !< pressure at each interface [R L2 T-2 ~> Pa] - temp_int, & !< temp and at interfaces [degC] - salt_int, & !< salt at at interfaces [ppt] + temp_int, & !< temp and at interfaces [C ~> degC] + salt_int, & !< salt at at interfaces [S ~> ppt] alpha_dT, & !< alpha*dT across interfaces [kg m-3] beta_dS, & !< beta*dS across interfaces [kg m-3] - dT, & !< temp. difference between adjacent layers [degC] - dS !< salt difference between adjacent layers [ppt] + dT, & !< temp. difference between adjacent layers [C ~> degC] + dS !< salt difference between adjacent layers [S ~> ppt] real, dimension(SZK_(GV)+1) :: & Kd1_T, & !< Diapycanal diffusivity of temperature [m2 s-1]. Kd1_S !< Diapycanal diffusivity of salinity [m2 s-1]. diff --git a/src/parameterizations/vertical/MOM_CVMix_shear.F90 b/src/parameterizations/vertical/MOM_CVMix_shear.F90 index db98e063d8..7ec45dbe11 100644 --- a/src/parameterizations/vertical/MOM_CVMix_shear.F90 +++ b/src/parameterizations/vertical/MOM_CVMix_shear.F90 @@ -82,8 +82,8 @@ subroutine calculate_CVMix_shear(u_H, v_H, h, tv, kd, kv, G, GV, US, CS ) real :: dummy ! A dummy variable [nondim] real :: dRho ! Buoyancy differences [Z T-2 ~> m s-2] real, dimension(2*(GV%ke)) :: pres_1d ! A column of interface pressures [R L2 T-2 ~> Pa] - real, dimension(2*(GV%ke)) :: temp_1d ! A column of temperatures [degC] - real, dimension(2*(GV%ke)) :: salt_1d ! A column of salinities [ppt] + real, dimension(2*(GV%ke)) :: temp_1d ! A column of temperatures [C ~> degC] + real, dimension(2*(GV%ke)) :: salt_1d ! A column of salinities [S ~> ppt] real, dimension(2*(GV%ke)) :: rho_1d ! A column of densities at interface pressures [R ~> kg m-3] real, dimension(GV%ke+1) :: Ri_Grad !< Gradient Richardson number [nondim] real, dimension(GV%ke+1) :: Kvisc !< Vertical viscosity at interfaces [m2 s-1] diff --git a/src/parameterizations/vertical/MOM_bulk_mixed_layer.F90 b/src/parameterizations/vertical/MOM_bulk_mixed_layer.F90 index 73fc288731..5df132a44d 100644 --- a/src/parameterizations/vertical/MOM_bulk_mixed_layer.F90 +++ b/src/parameterizations/vertical/MOM_bulk_mixed_layer.F90 @@ -57,7 +57,7 @@ module MOM_bulk_mixed_layer !! If the value is small enough, this should not affect the solution. real :: omega !< The Earth's rotation rate [T-1 ~> s-1]. real :: dT_dS_wt !< When forced to extrapolate T & S to match the - !! layer densities, this factor (in degC / ppt) is + !! layer densities, this factor [C S-1 ~> degC ppt-1] is !! combined with the derivatives of density with T & S !! to determines what direction is orthogonal to !! density contours. It should be a typical value of @@ -119,7 +119,7 @@ module MOM_bulk_mixed_layer real :: Allowed_T_chg !< The amount by which temperature is allowed !! to exceed previous values during detrainment, K. real :: Allowed_S_chg !< The amount by which salinity is allowed - !! to exceed previous values during detrainment, ppt. + !! to exceed previous values during detrainment [S ~> ppt] ! These are terms in the mixed layer TKE budget, all in [Z L2 T-3 ~> m3 s-3] except as noted. real, allocatable, dimension(:,:) :: & @@ -212,8 +212,8 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C ! will be used to hold the new mixed layer properties. real, dimension(SZI_(G),SZK0_(GV)) :: & h, & ! The layer thickness [H ~> m or kg m-2]. - T, & ! The layer temperatures [degC]. - S, & ! The layer salinities [ppt]. + T, & ! The layer temperatures [C ~> degC]. + S, & ! The layer salinities [S ~> ppt]. R0, & ! The potential density referenced to the surface [R ~> kg m-3]. Rcv ! The coordinate variable potential density [R ~> kg m-3]. real, dimension(SZI_(G),SZK_(GV)) :: & @@ -243,9 +243,9 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C Rcv_tot, & ! The integrated coordinate value potential density of the ! layers that are fully entrained [H R ~> kg m-2 or kg2 m-5]. Ttot, & ! The integrated temperature of layers which are fully - ! entrained [degC H ~> degC m or degC kg m-2]. + ! entrained [C H ~> degC m or degC kg m-2]. Stot, & ! The integrated salt of layers which are fully entrained - ! [H ppt ~> m ppt or ppt kg m-2]. + ! [H S ~> m ppt or ppt kg m-2]. uhtot, & ! The depth integrated zonal and meridional velocities in the vhtot, & ! mixed layer [H L T-1 ~> m2 s-1 or kg m-1 s-1]. @@ -254,28 +254,28 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C ! ocean over a time step [H ~> m or kg m-2]. NetMassOut, & ! The mass flux (if non-Boussinesq) or volume flux (if Boussinesq) ! over a time step from evaporating fresh water [H ~> m or kg m-2] - Net_heat, & ! The net heating at the surface over a time step [degC H ~> degC m or degC kg m-2]. + Net_heat, & ! The net heating at the surface over a time step [C H ~> degC m or degC kg m-2] ! Any penetrating shortwave radiation is not included in Net_heat. - Net_salt, & ! The surface salt flux into the ocean over a time step, ppt H. + Net_salt, & ! The surface salt flux into the ocean over a time step [S H ~> ppt m or ppt kg m-2] Idecay_len_TKE, & ! The inverse of a turbulence decay length scale [H-1 ~> m-1 or m2 kg-1]. p_ref, & ! Reference pressure for the potential density governing mixed ! layer dynamics, almost always 0 (or 1e5) [R L2 T-2 ~> Pa]. p_ref_cv, & ! Reference pressure for the potential density which defines ! the coordinate variable, set to P_Ref [R L2 T-2 ~> Pa]. dR0_dT, & ! Partial derivative of the mixed layer potential density with - ! temperature [R degC-1 ~> kg m-3 degC-1]. + ! temperature [R C-1 ~> kg m-3 degC-1]. dRcv_dT, & ! Partial derivative of the coordinate variable potential - ! density in the mixed layer with temperature [R degC-1 ~> kg m-3 degC-1]. + ! density in the mixed layer with temperature [R C-1 ~> kg m-3 degC-1]. dR0_dS, & ! Partial derivative of the mixed layer potential density with - ! salinity [R ppt-1 ~> kg m-3 ppt-1]. + ! salinity [R S-1 ~> kg m-3 ppt-1]. dRcv_dS, & ! Partial derivative of the coordinate variable potential - ! density in the mixed layer with salinity [R ppt-1 ~> kg m-3 ppt-1]. + ! density in the mixed layer with salinity [R S-1 ~> kg m-3 ppt-1]. TKE_river ! The source of turbulent kinetic energy available for mixing ! at rivermouths [Z L2 T-3 ~> m3 s-3]. real, dimension(max(CS%nsw,1),SZI_(G)) :: & Pen_SW_bnd ! The penetrating fraction of the shortwave heating integrated - ! over a time step in each band [degC H ~> degC m or degC kg m-2]. + ! over a time step in each band [C H ~> degC m or degC kg m-2]. real, dimension(max(CS%nsw,1),SZI_(G),SZK_(GV)) :: & opacity_band ! The opacity in each band [H-1 ~> m-1 or m2 kg-1]. The indicies are band, i, k. @@ -488,8 +488,8 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C ! We aggregate the thermodynamic forcing for a time step into the following: ! netMassInOut = water [H ~> m or kg m-2] added/removed via surface fluxes ! netMassOut = water [H ~> m or kg m-2] removed via evaporating surface fluxes - ! net_heat = heat via surface fluxes [degC H ~> degC m or degC kg m-2] - ! net_salt = salt via surface fluxes [ppt H ~> ppt m or gSalt m-2] + ! net_heat = heat via surface fluxes [C H ~> degC m or degC kg m-2] + ! net_salt = salt via surface fluxes [S H ~> ppt m or gSalt m-2] ! Pen_SW_bnd = components to penetrative shortwave radiation call extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & CS%H_limit_fluxes, CS%use_river_heat_content, CS%use_calving_heat_content, & @@ -505,7 +505,7 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C ! Now the mixed layer undergoes mechanically forced entrainment. ! The mixed layer may entrain down to the Monin-Obukhov depth if the - ! surface is becoming lighter, and is effecti1336vely detraining. + ! surface is becoming lighter, and is effectively detraining. ! First the TKE at the depth of free convection that is available ! to drive mixing is calculated. @@ -760,8 +760,8 @@ subroutine convective_adjustment(h, u, v, R0, Rcv, T, S, eps, d_eb, & !! surface pressure [R ~> kg m-3]. real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: Rcv !< The coordinate defining potential !! density [R ~> kg m-3]. - real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Layer temperatures [degC]. - real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Layer salinities [ppt]. + real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Layer temperatures [C ~> degC]. + real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Layer salinities [S ~> ppt]. real, dimension(SZI_(G),SZK_(GV)), intent(in) :: eps !< The negligibly small amount of water !! that will be left in each layer [H ~> m or kg m-2]. real, dimension(SZI_(G),SZK_(GV)), intent(inout) :: d_eb !< The downward increase across a layer @@ -788,9 +788,9 @@ subroutine convective_adjustment(h, u, v, R0, Rcv, T, S, eps, d_eb, & Rcv_tot, & ! The integrated coordinate value potential density of the ! layers that are fully entrained [H R ~> kg m-2 or kg2 m-5]. Ttot, & ! The integrated temperature of layers which are fully - ! entrained [degC H ~> degC m or degC kg m-2]. + ! entrained [C H ~> degC m or degC kg m-2]. Stot, & ! The integrated salt of layers which are fully entrained - ! [H ppt ~> m ppt or ppt kg m-2]. + ! [H S ~> m ppt or ppt kg m-2]. uhtot, & ! The depth integrated zonal and meridional velocities in vhtot, & ! the mixed layer [H L T-1 ~> m2 s-1 or kg m-1 s-1]. KE_orig, & ! The total mean kinetic energy per unit area in the mixed layer before @@ -890,9 +890,9 @@ subroutine mixedlayer_convection(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, & !! Positive values go with mass gain by a layer. real, dimension(SZI_(G)), intent(out) :: htot !< The accumulated mixed layer thickness [H ~> m or kg m-2]. real, dimension(SZI_(G)), intent(out) :: Ttot !< The depth integrated mixed layer temperature - !! [degC H ~> degC m or degC kg m-2]. + !! [C H ~> degC m or degC kg m-2]. real, dimension(SZI_(G)), intent(out) :: Stot !< The depth integrated mixed layer salinity - !! [ppt H ~> ppt m or ppt kg m-2]. + !! [S H ~> ppt m or ppt kg m-2]. real, dimension(SZI_(G)), intent(out) :: uhtot !< The depth integrated mixed layer zonal !! velocity [H L T-1 ~> m2 s-1 or kg m-1 s-1]. real, dimension(SZI_(G)), intent(out) :: vhtot !< The integrated mixed layer meridional @@ -906,9 +906,9 @@ subroutine mixedlayer_convection(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, & real, dimension(SZI_(G),SZK_(GV)), & intent(in) :: v !< Zonal velocities interpolated to h points [L T-1 ~> m s-1]. real, dimension(SZI_(G),SZK0_(GV)), & - intent(in) :: T !< Layer temperatures [degC]. + intent(in) :: T !< Layer temperatures [C ~> degC]. real, dimension(SZI_(G),SZK0_(GV)), & - intent(in) :: S !< Layer salinities [ppt]. + intent(in) :: S !< Layer salinities [C ~> ppt]. real, dimension(SZI_(G),SZK0_(GV)), & intent(in) :: R0 !< Potential density referenced to !! surface pressure [R ~> kg m-3]. @@ -919,28 +919,28 @@ subroutine mixedlayer_convection(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, & intent(in) :: eps !< The negligibly small amount of water !! that will be left in each layer [H ~> m or kg m-2]. real, dimension(SZI_(G)), intent(in) :: dR0_dT !< The partial derivative of R0 with respect to - !! temperature [R degC-1 ~> kg m-3 degC-1]. + !! temperature [R C-1 ~> kg m-3 degC-1]. real, dimension(SZI_(G)), intent(in) :: dRcv_dT !< The partial derivative of Rcv with respect to - !! temperature [R degC-1 ~> kg m-3 degC-1]. + !! temperature [R C-1 ~> kg m-3 degC-1]. real, dimension(SZI_(G)), intent(in) :: dR0_dS !< The partial derivative of R0 with respect to - !! salinity [R ppt-1 ~> kg m-3 ppt-1]. + !! salinity [R S-1 ~> kg m-3 ppt-1]. real, dimension(SZI_(G)), intent(in) :: dRcv_dS !< The partial derivative of Rcv with respect to - !! salinity [R ppt-1 ~> kg m-3 ppt-1]. + !! salinity [R S-1 ~> kg m-3 ppt-1]. real, dimension(SZI_(G)), intent(in) :: netMassInOut !< The net mass flux (if non-Boussinesq) !! or volume flux (if Boussinesq) into the ocean !! within a time step [H ~> m or kg m-2]. (I.e. P+R-E.) real, dimension(SZI_(G)), intent(in) :: netMassOut !< The mass or volume flux out of the ocean !! within a time step [H ~> m or kg m-2]. real, dimension(SZI_(G)), intent(in) :: Net_heat !< The net heating at the surface over a time - !! step [degC H ~> degC m or degC kg m-2]. Any penetrating + !! step [C H ~> degC m or degC kg m-2]. Any penetrating !! shortwave radiation is not included in Net_heat. real, dimension(SZI_(G)), intent(in) :: Net_salt !< The net surface salt flux into the ocean - !! over a time step [ppt H ~> ppt m or ppt kg m-2]. + !! over a time step [S H ~> ppt m or ppt kg m-2]. integer, intent(in) :: nsw !< The number of bands of penetrating !! shortwave radiation. real, dimension(max(nsw,1),SZI_(G)), intent(inout) :: Pen_SW_bnd !< The penetrating shortwave !! heating at the sea surface in each penetrating - !! band [degC H ~> degC m or degC kg m-2]. + !! band [C H ~> degC m or degC kg m-2]. real, dimension(max(nsw,1),SZI_(G),SZK_(GV)), intent(in) :: opacity_band !< The opacity in each band of !! penetrating shortwave radiation [H-1 ~> m-1 or m2 kg-1]. real, dimension(SZI_(G)), intent(out) :: Conv_En !< The buoyant turbulent kinetic energy source @@ -975,11 +975,11 @@ subroutine mixedlayer_convection(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, & real :: SW_trans ! The fraction of shortwave radiation ! that is not absorbed in a layer [nondim]. real :: Pen_absorbed ! The amount of penetrative shortwave radiation - ! that is absorbed in a layer [degC H ~> degC m or degC kg m-2]. + ! that is absorbed in a layer [C H ~> degC m or degC kg m-2]. real :: h_avail ! The thickness in a layer available for ! entrainment [H ~> m or kg m-2]. real :: h_ent ! The thickness from a layer that is entrained [H ~> m or kg m-2]. - real :: T_precip ! The temperature of the precipitation [degC]. + real :: T_precip ! The temperature of the precipitation [C ~> degC]. real :: C1_3, C1_6 ! 1/3 and 1/6. real :: En_fn, Frac, x1 ! Nondimensional temporary variables. real :: dr, dr0 ! Temporary variables [R H ~> kg m-2 or kg2 m-5]. @@ -1061,7 +1061,7 @@ subroutine mixedlayer_convection(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, & Conv_En(i) = 0.0 ; dKE_FC(i) = 0.0 if (associated(fluxes%heat_content_massin)) & fluxes%heat_content_massin(i,j) = fluxes%heat_content_massin(i,j) + & - T_precip * netMassIn(i) * GV%H_to_RZ * fluxes%C_p * Idt + T_precip * netMassIn(i) * GV%H_to_RZ * tv%C_p * Idt if (associated(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + & T_precip * netMassIn(i) * GV%H_to_RZ else ! This is a massless column, but zero out the summed variables anyway for safety. @@ -1112,12 +1112,12 @@ subroutine mixedlayer_convection(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, & d_eb(i,k) = d_eb(i,k) - h_evap ! smg: when resolve the A=B code, we will set - ! heat_content_massout = heat_content_massout - T(i,k)*h_evap*GV%H_to_RZ*fluxes%C_p*Idt + ! heat_content_massout = heat_content_massout - T(i,k)*h_evap*GV%H_to_RZ*tv%C_p*Idt ! by uncommenting the lines here. ! we will also then completely remove TempXpme from the model. if (associated(fluxes%heat_content_massout)) & fluxes%heat_content_massout(i,j) = fluxes%heat_content_massout(i,j) - & - T(i,k)*h_evap*GV%H_to_RZ * fluxes%C_p * Idt + T(i,k)*h_evap*GV%H_to_RZ * tv%C_p * Idt if (associated(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) - & T(i,k)*h_evap*GV%H_to_RZ @@ -1449,9 +1449,9 @@ subroutine mechanical_entrainment(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, & !! Positive values go with mass gain by a layer. real, dimension(SZI_(G)), intent(inout) :: htot !< The accumlated mixed layer thickness [H ~> m or kg m-2]. real, dimension(SZI_(G)), intent(inout) :: Ttot !< The depth integrated mixed layer temperature - !! [degC H ~> degC m or degC kg m-2]. + !! [C H ~> degC m or degC kg m-2]. real, dimension(SZI_(G)), intent(inout) :: Stot !< The depth integrated mixed layer salinity - !! [ppt H ~> ppt m or ppt kg m-2]. + !! [S H ~> ppt m or ppt kg m-2]. real, dimension(SZI_(G)), intent(inout) :: uhtot !< The depth integrated mixed layer zonal !! velocity [H L T-1 ~> m2 s-1 or kg m-1 s-1]. real, dimension(SZI_(G)), intent(inout) :: vhtot !< The integrated mixed layer meridional @@ -1465,9 +1465,9 @@ subroutine mechanical_entrainment(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, & real, dimension(SZI_(G),SZK_(GV)), & intent(in) :: v !< Zonal velocities interpolated to h points [L T-1 ~> m s-1]. real, dimension(SZI_(G),SZK0_(GV)), & - intent(in) :: T !< Layer temperatures [degC]. + intent(in) :: T !< Layer temperatures [C ~> degC]. real, dimension(SZI_(G),SZK0_(GV)), & - intent(in) :: S !< Layer salinities [ppt]. + intent(in) :: S !< Layer salinities [S ~> ppt]. real, dimension(SZI_(G),SZK0_(GV)), & intent(in) :: R0 !< Potential density referenced to !! surface pressure [R ~> kg m-3]. @@ -1478,9 +1478,9 @@ subroutine mechanical_entrainment(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, & intent(in) :: eps !< The negligibly small amount of water !! that will be left in each layer [H ~> m or kg m-2]. real, dimension(SZI_(G)), intent(in) :: dR0_dT !< The partial derivative of R0 with respect to - !! temperature [R degC-1 ~> kg m-3 degC-1]. + !! temperature [R C-1 ~> kg m-3 degC-1]. real, dimension(SZI_(G)), intent(in) :: dRcv_dT !< The partial derivative of Rcv with respect to - !! temperature [R degC-1 ~> kg m-3 degC-1]. + !! temperature [R C-1 ~> kg m-3 degC-1]. real, dimension(2,SZI_(G)), intent(in) :: cMKE !< Coefficients of HpE and HpE^2 used in calculating the !! denominator of MKE_rate; the two elements have differing !! units of [H-1 ~> m-1 or m2 kg-1] and [H-2 ~> m-2 or m4 kg-2]. @@ -1490,7 +1490,7 @@ subroutine mechanical_entrainment(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, & !! shortwave radiation. real, dimension(max(nsw,1),SZI_(G)), intent(inout) :: Pen_SW_bnd !< The penetrating shortwave !! heating at the sea surface in each penetrating - !! band [degC H ~> degC m or degC kg m-2]. + !! band [C H ~> degC m or degC kg m-2]. real, dimension(max(nsw,1),SZI_(G),SZK_(GV)), intent(in) :: opacity_band !< The opacity in each band of !! penetrating shortwave radiation [H-1 ~> m-1 or m2 kg-1]. real, dimension(SZI_(G)), intent(inout) :: TKE !< The turbulent kinetic energy @@ -1508,7 +1508,7 @@ subroutine mechanical_entrainment(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, & real :: SW_trans ! The fraction of shortwave radiation that is not ! absorbed in a layer, nondimensional. real :: Pen_absorbed ! The amount of penetrative shortwave radiation - ! that is absorbed in a layer [degC H ~> degC m or degC kg m-2]. + ! that is absorbed in a layer [C H ~> degC m or degC kg m-2]. real :: h_avail ! The thickness in a layer available for entrainment [H ~> m or kg m-2]. real :: h_ent ! The thickness from a layer that is entrained [H ~> m or kg m-2]. real :: h_min, h_max ! Limits on the solution for h_ent [H ~> m or kg m-2]. @@ -1832,8 +1832,8 @@ subroutine resort_ML(h, T, S, R0, Rcv, RcvTgt, eps, d_ea, d_eb, ksort, G, GV, CS !! structure. real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2]. !! Layer 0 is the new mixed layer. - real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Layer temperatures [degC]. - real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Layer salinities [ppt]. + real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Layer temperatures [C ~> degC]. + real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Layer salinities [S ~> ppt]. real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: R0 !< Potential density referenced to !! surface pressure [R ~> kg m-3]. real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: Rcv !< The coordinate defining @@ -1856,19 +1856,19 @@ subroutine resort_ML(h, T, S, R0, Rcv, RcvTgt, eps, d_ea, d_eb, ksort, G, GV, CS real, dimension(SZI_(G)), intent(in) :: dR0_dT !< The partial derivative of !! potential density referenced !! to the surface with potential - !! temperature [R degC-1 ~> kg m-3 degC-1]. + !! temperature [R C-1 ~> kg m-3 degC-1]. real, dimension(SZI_(G)), intent(in) :: dR0_dS !< The partial derivative of !! cpotential density referenced !! to the surface with salinity, - !! [R ppt-1 ~> kg m-3 ppt-1]. + !! [R S-1 ~> kg m-3 ppt-1]. real, dimension(SZI_(G)), intent(in) :: dRcv_dT !< The partial derivative of !! coordinate defining potential !! density with potential - !! temperature [R degC-1 ~> kg m-3 degC-1]. + !! temperature [R C-1 ~> kg m-3 degC-1]. real, dimension(SZI_(G)), intent(in) :: dRcv_dS !< The partial derivative of !! coordinate defining potential !! density with salinity, - !! [R ppt-1 ~> kg m-3 ppt-1]. + !! [R S-1 ~> kg m-3 ppt-1]. ! If there are no massive light layers above the deepest of the mixed- and ! buffer layers, do nothing (except perhaps to reshuffle these layers). @@ -2151,8 +2151,8 @@ subroutine mixedlayer_detrain_2(h, T, S, R0, Rcv, RcvTgt, dt, dt_diag, d_ea, j, type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure. real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2]. !! Layer 0 is the new mixed layer. - real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Potential temperature [degC]. - real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Salinity [ppt]. + real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Potential temperature [C ~> degC]. + real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Salinity [S ~> ppt]. real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: R0 !< Potential density referenced to !! surface pressure [R ~> kg m-3]. real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: Rcv !< The coordinate defining potential @@ -2171,18 +2171,18 @@ subroutine mixedlayer_detrain_2(h, T, S, R0, Rcv, RcvTgt, dt, dt_diag, d_ea, j, real, dimension(SZI_(G)), intent(in) :: dR0_dT !< The partial derivative of !! potential density referenced to the !! surface with potential temperature, - !! [R degC-1 ~> kg m-3 degC-1]. + !! [R C-1 ~> kg m-3 degC-1]. real, dimension(SZI_(G)), intent(in) :: dR0_dS !< The partial derivative of !! cpotential density referenced to the !! surface with salinity - !! [R ppt-1 ~> kg m-3 ppt-1]. + !! [R S-1 ~> kg m-3 ppt-1]. real, dimension(SZI_(G)), intent(in) :: dRcv_dT !< The partial derivative of !! coordinate defining potential density !! with potential temperature, - !! [R degC-1 ~> kg m-3 degC-1]. + !! [R C-1 ~> kg m-3 degC-1]. real, dimension(SZI_(G)), intent(in) :: dRcv_dS !< The partial derivative of !! coordinate defining potential density - !! with salinity [R ppt-1 ~> kg m-3 ppt-1]. + !! with salinity [R S-1 ~> kg m-3 ppt-1]. real, dimension(SZI_(G)), intent(in) :: max_BL_det !< If non-negative, the maximum !! detrainment permitted from the buffer !! layers [H ~> m or kg m-2]. @@ -2199,9 +2199,9 @@ subroutine mixedlayer_detrain_2(h, T, S, R0, Rcv, RcvTgt, dt, dt_diag, d_ea, j, real :: Rcv_to_bl ! The depth integrated amount of Rcv that is detrained to the ! buffer layer [H R ~> kg m-2 or kg2 m-5] real :: T_to_bl ! The depth integrated amount of T that is detrained to the - ! buffer layer [degC H ~> degC m or degC kg m-2] + ! buffer layer [C H ~> degC m or degC kg m-2] real :: S_to_bl ! The depth integrated amount of S that is detrained to the - ! buffer layer [ppt H ~> ppt m or ppt kg m-2] + ! buffer layer [S H ~> ppt m or ppt kg m-2] real :: h_min_bl ! The minimum buffer layer thickness [H ~> m or kg m-2]. real :: h1, h2 ! Scalar variables holding the values of @@ -2248,9 +2248,9 @@ subroutine mixedlayer_detrain_2(h, T, S, R0, Rcv, RcvTgt, dt, dt_diag, d_ea, j, ! interior layers that are just lighter and ! just denser than the lower buffer layer. - real :: R0_det, T_det, S_det ! Detrained values of R0 [R ~> kg m-3], T [degC], and S [ppt]. - real :: Rcv_stays, R0_stays ! Values of Rcv and R0 that stay in a layer. - real :: T_stays, S_stays ! Values of T and S that stay in a layer. + real :: R0_det, T_det, S_det ! Detrained values of R0 [R ~> kg m-3], T [C ~> degC] and S [S ~> ppt] + real :: Rcv_stays, R0_stays ! Values of Rcv and R0 that stay in a layer [R ~> kg m-3] + real :: T_stays, S_stays ! Values of T and S that stay in a layer, [C ~> degC] and S [S ~> ppt] real :: dSpice_det, dSpice_stays! The spiciness difference between an original ! buffer layer and the water that moves into ! an interior layer or that stays in that @@ -2269,8 +2269,8 @@ subroutine mixedlayer_detrain_2(h, T, S, R0, Rcv, RcvTgt, dt, dt_diag, d_ea, j, real :: dPE_time_ratio ! Larger of 1 and the detrainment timescale over dt [nondim]. real :: dT_dS_gauge, dS_dT_gauge ! The relative scales of temperature and ! salinity changes in defining spiciness, in - ! [degC ppt-1] and [ppt degC-1]. - real :: I_denom ! A work variable with units of [ppt2 R-2 ~> ppt2 m6 kg-2]. + ! [C S-1 ~> degC ppt-1] and [S C-1 ~> ppt degC-1]. + real :: I_denom ! A work variable with units of [S2 R-2 ~> ppt2 m6 kg-2]. real :: g_2 ! 1/2 g_Earth [L2 Z-1 T-2 ~> m s-2]. real :: Rho0xG ! Rho0 times G_Earth [R L2 Z-1 T-2 ~> kg m-2 s-2]. @@ -3040,8 +3040,8 @@ subroutine mixedlayer_detrain_1(h, T, S, R0, Rcv, RcvTgt, dt, dt_diag, d_ea, d_e type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure. real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2]. !! Layer 0 is the new mixed layer. - real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Potential temperature [degC]. - real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Salinity [ppt]. + real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Potential temperature [C ~> degC]. + real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Salinity [S ~> ppt]. real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: R0 !< Potential density referenced to !! surface pressure [R ~> kg m-3]. real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: Rcv !< The coordinate defining potential @@ -3065,10 +3065,10 @@ subroutine mixedlayer_detrain_1(h, T, S, R0, Rcv, RcvTgt, dt, dt_diag, d_ea, d_e real, dimension(SZI_(G)), intent(in) :: dRcv_dT !< The partial derivative of !! coordinate defining potential density !! with potential temperature - !! [R degC-1 ~> kg m-3 degC-1]. + !! [R C-1 ~> kg m-3 degC-1]. real, dimension(SZI_(G)), intent(in) :: dRcv_dS !< The partial derivative of !! coordinate defining potential density - !! with salinity [R ppt-1 ~> kg m-3 ppt-1]. + !! with salinity [R S-1 ~> kg m-3 ppt-1]. real, dimension(SZI_(G)), intent(in) :: max_BL_det !< If non-negative, the maximum !! detrainment permitted from the buffer !! layers [H ~> m or kg m-2]. @@ -3081,8 +3081,8 @@ subroutine mixedlayer_detrain_1(h, T, S, R0, Rcv, RcvTgt, dt, dt_diag, d_ea, d_e real :: detrain(SZI_(G)) ! The thickness of fluid to detrain ! from the mixed layer [H ~> m or kg m-2]. real :: dT_dR, dS_dR, dRml, dR0_dRcv, dT_dS_wt2 - real :: I_denom ! A work variable [ppt2 R-2 ~> ppt2 m6 kg-2]. - real :: Sdown, Tdown + real :: I_denom ! A work variable [S2 R-2 ~> ppt2 m6 kg-2]. + real :: Sdown, Tdown ! A salinity [S ~> ppt] and a temperature [C ~> degC] real :: dt_Time ! The timestep divided by the detrainment timescale [nondim]. real :: g_H2_2Rho0dt ! Half the gravitational acceleration times the square of the ! conversion from H to m divided by the mean density times the time @@ -3396,18 +3396,18 @@ subroutine bulkmixedlayer_init(Time, G, GV, US, param_file, diag, CS) "If true, limit the detrainment from the buffer layers "//& "to not be too different from the neighbors.", default=.false.) call get_param(param_file, mdl, "ALLOWED_DETRAIN_TEMP_CHG", CS%Allowed_T_chg, & - "The amount by which temperature is allowed to exceed "//& - "previous values during detrainment.", units="K", default=0.5) + "The amount by which temperature is allowed to exceed previous values "//& + "during detrainment.", units="K", default=0.5, scale=US%degC_to_C) call get_param(param_file, mdl, "ALLOWED_DETRAIN_SALT_CHG", CS%Allowed_S_chg, & - "The amount by which salinity is allowed to exceed "//& - "previous values during detrainment.", units="PSU", default=0.1) + "The amount by which salinity is allowed to exceed previous values "//& + "during detrainment.", units="PSU", default=0.1, scale=US%ppt_to_S) call get_param(param_file, mdl, "ML_DT_DS_WEIGHT", CS%dT_dS_wt, & "When forced to extrapolate T & S to match the layer "//& "densities, this factor (in deg C / PSU) is combined "//& "with the derivatives of density with T & S to determine "//& "what direction is orthogonal to density contours. It "//& - "should be a typical value of (dR/dS) / (dR/dT) in "//& - "oceanic profiles.", units="degC PSU-1", default=6.0) + "should be a typical value of (dR/dS) / (dR/dT) in oceanic profiles.", & + units="degC PSU-1", default=6.0, scale=US%degC_to_C*US%S_to_ppt) call get_param(param_file, mdl, "BUFFER_LAYER_EXTRAP_LIMIT", CS%BL_extrap_lim, & "A limit on the density range over which extrapolation "//& "can occur when detraining from the buffer layers, "//& diff --git a/src/parameterizations/vertical/MOM_diabatic_aux.F90 b/src/parameterizations/vertical/MOM_diabatic_aux.F90 index 86df042646..11c168c2cc 100644 --- a/src/parameterizations/vertical/MOM_diabatic_aux.F90 +++ b/src/parameterizations/vertical/MOM_diabatic_aux.F90 @@ -106,7 +106,7 @@ subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo) intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2] type(thermo_var_ptrs), intent(inout) :: tv !< Structure containing pointers to any available !! thermodynamic fields. - type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(diabatic_aux_CS), intent(in) :: CS !< The control structure returned by a previous !! call to diabatic_aux_init. real, dimension(SZI_(G),SZJ_(G)), & @@ -116,12 +116,12 @@ subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo) ! Local variables real, dimension(SZI_(G)) :: & fraz_col, & ! The accumulated heat requirement due to frazil [Q R Z ~> J m-2]. - T_freeze, & ! The freezing potential temperature at the current salinity [degC]. + T_freeze, & ! The freezing potential temperature at the current salinity [C ~> degC]. ps ! Surface pressure [R L2 T-2 ~> Pa] real, dimension(SZI_(G),SZK_(GV)) :: & pressure ! The pressure at the middle of each layer [R L2 T-2 ~> Pa]. real :: H_to_RL2_T2 ! A conversion factor from thicknesses in H to pressure [R L2 T-2 H-1 ~> Pa m-1 or Pa m2 kg-1] - real :: hc ! A layer's heat capacity [Q R Z degC-1 ~> J m-2 degC-1]. + real :: hc ! A layer's heat capacity [Q R Z C-1 ~> J m-2 degC-1]. logical :: T_fr_set ! True if the freezing point has been calculated for a ! row of points. integer :: i, j, k, is, ie, js, je, nz @@ -162,8 +162,8 @@ subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo) T_fr_set = .false. do i=is,ie ; if (tv%frazil(i,j) > 0.0) then if (.not.T_fr_set) then - call calculate_TFreeze(tv%S(i:,j,1), pressure(i:,1), T_freeze(i:), & - 1, ie-i+1, tv%eqn_of_state, pres_scale=US%RL2_T2_to_Pa) + call calculate_TFreeze(tv%S(i:ie,j,1), pressure(i:ie,1), T_freeze(i:ie), & + tv%eqn_of_state) T_fr_set = .true. endif @@ -188,8 +188,8 @@ subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo) if ((G%mask2dT(i,j) > 0.0) .and. & ((tv%T(i,j,k) < 0.0) .or. (fraz_col(i) > 0.0))) then if (.not.T_fr_set) then - call calculate_TFreeze(tv%S(i:,j,k), pressure(i:,k), T_freeze(i:), & - 1, ie-i+1, tv%eqn_of_state, pres_scale=US%RL2_T2_to_Pa) + call calculate_TFreeze(tv%S(i:ie,j,k), pressure(i:ie,k), T_freeze(i:ie), & + tv%eqn_of_state) T_fr_set = .true. endif @@ -228,9 +228,9 @@ subroutine differential_diffuse_T_S(h, T, S, Kd_T, Kd_S, dt, G, GV) 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)), & - intent(inout) :: T !< Potential temperature [degC]. + intent(inout) :: T !< Potential temperature [C ~> degC]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(inout) :: S !< Salinity [PSU] or [gSalt/kg], generically [ppt]. + intent(inout) :: S !< Salinity [PSU] or [gSalt/kg], generically [S ~> ppt]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), & intent(inout) :: Kd_T !< The extra diffusivity of temperature due to !! double diffusion relative to the diffusivity of @@ -329,8 +329,8 @@ subroutine adjust_salt(h, tv, G, GV, CS) !! call to diabatic_aux_init. ! local variables - real :: salt_add_col(SZI_(G),SZJ_(G)) !< The accumulated salt requirement [ppt R Z ~> gSalt m-2] - real :: S_min !< The minimum salinity [ppt]. + real :: salt_add_col(SZI_(G),SZJ_(G)) !< The accumulated salt requirement [S R Z ~> gSalt m-2] + real :: S_min !< The minimum salinity [S ~> ppt]. real :: mc !< A layer's mass [R Z ~> kg m-2]. integer :: i, j, k, is, ie, js, je, nz @@ -386,8 +386,8 @@ subroutine triDiagTS(G, GV, is, ie, js, je, hold, ea, eb, T, S) !! above within this time step [H ~> m or kg m-2] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: eb !< The amount of fluid entrained from the layer !! below within this time step [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: T !< Layer potential temperatures [degC]. - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: S !< Layer salinities [ppt]. + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: T !< Layer potential temperatures [C ~> degC]. + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: S !< Layer salinities [S ~> ppt]. ! Local variables real :: b1(SZIB_(G)) ! A variable used by the tridiagonal solver [H-1 ~> m-1 or m2 kg-1]. @@ -434,8 +434,8 @@ subroutine triDiagTS_Eulerian(G, GV, is, ie, js, je, hold, ent, T, S) !! [H ~> m or kg m-2]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), intent(in) :: ent !< The amount of fluid mixed across an interface !! within this time step [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: T !< Layer potential temperatures [degC]. - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: S !< Layer salinities [ppt]. + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: T !< Layer potential temperatures [C ~> degC]. + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: S !< Layer salinities [S ~> ppt]. ! Local variables real :: b1(SZIB_(G)) ! A variable used by the tridiagonal solver [H-1 ~> m-1 or m2 kg-1]. @@ -672,8 +672,8 @@ subroutine diagnoseMLDbyDensityDifference(id_MLD, h, tv, densityDiff, G, GV, US, real, dimension(SZI_(G)) :: deltaRhoAtKm1, deltaRhoAtK ! Density differences [R ~> kg m-3]. real, dimension(SZI_(G)) :: pRef_MLD, pRef_N2 ! Reference pressures [R L2 T-2 ~> Pa]. real, dimension(SZI_(G)) :: H_subML, dH_N2 ! Summed thicknesses used in N2 calculation [H ~> m]. - real, dimension(SZI_(G)) :: T_subML, T_deeper ! Temperatures used in the N2 calculation [degC]. - real, dimension(SZI_(G)) :: S_subML, S_deeper ! Salinities used in the N2 calculation [ppt]. + real, dimension(SZI_(G)) :: T_subML, T_deeper ! Temperatures used in the N2 calculation [C ~> degC]. + real, dimension(SZI_(G)) :: S_subML, S_deeper ! Salinities used in the N2 calculation [S ~> ppt]. real, dimension(SZI_(G)) :: rho_subML, rho_deeper ! Densities used in the N2 calculation [R ~> kg m-3]. real, dimension(SZI_(G)) :: dK, dKm1 ! Depths [Z ~> m]. real, dimension(SZI_(G)) :: rhoSurf ! Density used in finding the mixed layer depth [R ~> kg m-3]. @@ -1036,10 +1036,10 @@ subroutine applyBoundaryFluxesInOut(CS, G, GV, US, dt, fluxes, optics, nsw, h, t !! forcing through each layer [R Z3 T-2 ~> J m-2] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & optional, intent(out) :: dSV_dT !< Partial derivative of specific volume with - !! potential temperature [R-1 degC-1 ~> m3 kg-1 degC-1]. + !! potential temperature [R-1 C-1 ~> m3 kg-1 degC-1]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & optional, intent(out) :: dSV_dS !< Partial derivative of specific volume with - !! salinity [R-1 ppt-1 ~> m3 kg-1 ppt-1]. + !! salinity [R-1 S-1 ~> m3 kg-1 ppt-1]. real, dimension(SZI_(G),SZJ_(G)), & optional, intent(out) :: SkinBuoyFlux !< Buoyancy flux at surface [Z2 T-3 ~> m2 s-3]. @@ -1061,32 +1061,32 @@ subroutine applyBoundaryFluxesInOut(CS, G, GV, US, dt, fluxes, optics, nsw, h, t netMassIn, & ! mass entering ocean surface [H ~> m or kg m-2] over a time step netMassOut, & ! mass leaving ocean surface [H ~> m or kg m-2] over a time step netHeat, & ! heat via surface fluxes excluding Pen_SW_bnd and netMassOut - ! [degC H ~> degC m or degC kg m-2] + ! [C H ~> degC m or degC kg m-2] netSalt, & ! surface salt flux ( g(salt)/m2 for non-Bouss and ppt*H for Bouss ) - ! [ppt H ~> ppt m or ppt kg m-2] + ! [S H ~> ppt m or ppt kg m-2] nonpenSW, & ! non-downwelling SW, which is absorbed at ocean surface - ! [degC H ~> degC m or degC kg m-2] + ! [C H ~> degC m or degC kg m-2] SurfPressure, & ! Surface pressure (approximated as 0.0) [R L2 T-2 ~> Pa] - dRhodT, & ! change in density per change in temperature [R degC-1 ~> kg m-3 degC-1] - dRhodS, & ! change in density per change in salinity [R ppt-1 ~> kg m-3 ppt-1] - netheat_rate, & ! netheat but for dt=1 [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] + dRhodT, & ! change in density per change in temperature [R C-1 ~> kg m-3 degC-1] + dRhodS, & ! change in density per change in salinity [R S-1 ~> kg m-3 ppt-1] + netheat_rate, & ! netheat but for dt=1 [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] netsalt_rate, & ! netsalt but for dt=1 (e.g. returns a rate) - ! [ppt H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] + ! [S H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] netMassInOut_rate! netmassinout but for dt=1 [H T-1 ~> m s-1 or kg m-2 s-1] real, dimension(SZI_(G), SZK_(GV)) :: & h2d, & ! A 2-d copy of the thicknesses [H ~> m or kg m-2] - T2d, & ! A 2-d copy of the layer temperatures [degC] + T2d, & ! A 2-d copy of the layer temperatures [C ~> degC] pen_TKE_2d, & ! The TKE required to homogenize the heating by shortwave radiation within ! a layer [R Z3 T-2 ~> J m-2] - dSV_dT_2d ! The partial derivative of specific volume with temperature [R-1 degC-1 ~> m3 kg-1 degC-1] + dSV_dT_2d ! The partial derivative of specific volume with temperature [R-1 C-1 ~> m3 kg-1 degC-1] real, dimension(SZI_(G)) :: & netPen_rate ! The surface penetrative shortwave heating rate summed over all bands - ! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] + ! [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] real, dimension(max(nsw,1),SZI_(G)) :: & Pen_SW_bnd, & ! The penetrative shortwave heating integrated over a timestep by band - ! [degC H ~> degC m or degC kg m-2] + ! [C H ~> degC m or degC kg m-2] Pen_SW_bnd_rate ! The penetrative shortwave heating rate by band - ! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] + ! [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] real, dimension(max(nsw,1),SZI_(G),SZK_(GV)) :: & opacityBand ! The opacity (inverse of the exponential absorption length) of each frequency ! band of shortwave radiation in each layer [H-1 ~> m-1 or m2 kg-1] @@ -1190,9 +1190,9 @@ subroutine applyBoundaryFluxesInOut(CS, G, GV, US, dt, fluxes, optics, nsw, h, t ! note that lprec generally has sea ice melt/form included. ! netMassOut = net mass leaving ocean surface [H ~> m or kg m-2] over a time step. ! netMassOut < 0 means mass leaves ocean. - ! netHeat = heat via surface fluxes [degC H ~> degC m or degC kg m-2], excluding the part + ! netHeat = heat via surface fluxes [C H ~> degC m or degC kg m-2], excluding the part ! contained in Pen_SW_bnd; and excluding heat_content of netMassOut < 0. - ! netSalt = surface salt fluxes [ppt H ~> ppt m or gSalt m-2] + ! netSalt = surface salt fluxes [S H ~> ppt m or gSalt m-2] ! Pen_SW_bnd = components to penetrative shortwave radiation split according to bands. ! This field provides that portion of SW from atmosphere that in fact ! enters to the ocean and participates in penetrative SW heating. @@ -1284,10 +1284,10 @@ subroutine applyBoundaryFluxesInOut(CS, G, GV, US, dt, fluxes, optics, nsw, h, t ! Diagnostics of heat content associated with mass fluxes if (associated(fluxes%heat_content_massin)) & fluxes%heat_content_massin(i,j) = fluxes%heat_content_massin(i,j) + & - T2d(i,k) * max(0.,dThickness) * GV%H_to_RZ * fluxes%C_p * Idt + T2d(i,k) * max(0.,dThickness) * GV%H_to_RZ * tv%C_p * Idt if (associated(fluxes%heat_content_massout)) & fluxes%heat_content_massout(i,j) = fluxes%heat_content_massout(i,j) + & - T2d(i,k) * min(0.,dThickness) * GV%H_to_RZ * fluxes%C_p * Idt + T2d(i,k) * min(0.,dThickness) * GV%H_to_RZ * tv%C_p * Idt if (associated(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + & T2d(i,k) * dThickness * GV%H_to_RZ @@ -1367,10 +1367,10 @@ subroutine applyBoundaryFluxesInOut(CS, G, GV, US, dt, fluxes, optics, nsw, h, t ! Diagnostics of heat content associated with mass fluxes if (associated(fluxes%heat_content_massin)) & fluxes%heat_content_massin(i,j) = fluxes%heat_content_massin(i,j) + & - T2d(i,k) * max(0.,dThickness) * GV%H_to_RZ * fluxes%C_p * Idt + T2d(i,k) * max(0.,dThickness) * GV%H_to_RZ * tv%C_p * Idt if (associated(fluxes%heat_content_massout)) & fluxes%heat_content_massout(i,j) = fluxes%heat_content_massout(i,j) + & - T2d(i,k) * min(0.,dThickness) * GV%H_to_RZ * fluxes%C_p * Idt + T2d(i,k) * min(0.,dThickness) * GV%H_to_RZ * tv%C_p * Idt if (associated(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + & T2d(i,k) * dThickness * GV%H_to_RZ @@ -1395,8 +1395,10 @@ subroutine applyBoundaryFluxesInOut(CS, G, GV, US, dt, fluxes, optics, nsw, h, t elseif (h2d(i,k) < 0.0) then ! h2d==0 is a special limit that needs no extra handling call forcing_SinglePointPrint(fluxes,G,i,j,'applyBoundaryFluxesInOut (h<0)') write(0,*) 'applyBoundaryFluxesInOut(): lon,lat=',G%geoLonT(i,j),G%geoLatT(i,j) - write(0,*) 'applyBoundaryFluxesInOut(): netT,netS,netH=',netHeat(i),netSalt(i),netMassInOut(i) - write(0,*) 'applyBoundaryFluxesInOut(): dT,dS,dH=',dTemp,dSalt,dThickness + write(0,*) 'applyBoundaryFluxesInOut(): netT,netS,netH=', & + US%C_to_degC*netHeat(i), US%S_to_ppt*netSalt(i), netMassInOut(i) + write(0,*) 'applyBoundaryFluxesInOut(): dT,dS,dH=', & + US%C_to_degC*dTemp, US%S_to_ppt*dSalt, dThickness write(0,*) 'applyBoundaryFluxesInOut(): h(n),h(n+1),k=',hOld,h2d(i,k),k call MOM_error(FATAL, "MOM_diabatic_aux.F90, applyBoundaryFluxesInOut(): "//& "Complete mass loss in column!") @@ -1411,7 +1413,7 @@ subroutine applyBoundaryFluxesInOut(CS, G, GV, US, dt, fluxes, optics, nsw, h, t call forcing_SinglePointPrint(fluxes,G,i,j,'applyBoundaryFluxesInOut (land)') write(0,*) 'applyBoundaryFluxesInOut(): lon,lat=',G%geoLonT(i,j),G%geoLatT(i,j) write(0,*) 'applyBoundaryFluxesInOut(): netHeat,netSalt,netMassIn,netMassOut=',& - netHeat(i),netSalt(i),netMassIn(i),netMassOut(i) + US%C_to_degC*netHeat(i), US%S_to_ppt*netSalt(i), netMassIn(i), netMassOut(i) call MOM_error(FATAL, "MOM_diabatic_aux.F90, applyBoundaryFluxesInOut(): "//& "Mass loss over land?") @@ -1476,6 +1478,7 @@ subroutine applyBoundaryFluxesInOut(CS, G, GV, US, dt, fluxes, optics, nsw, h, t ! convergence of SW into a layer do k=1,nz ; do i=is,ie + ! Note that the units of penSW_diag change here, from [C ~> degC] to [Q R Z T-1 ~> W m-2]. CS%penSW_diag(i,j,k) = (T2d(i,k)-CS%penSW_diag(i,j,k))*h(i,j,k) * Idt * tv%C_p * GV%H_to_RZ enddo ; enddo diff --git a/src/parameterizations/vertical/MOM_diabatic_driver.F90 b/src/parameterizations/vertical/MOM_diabatic_driver.F90 index ab531d4158..61c30830a8 100644 --- a/src/parameterizations/vertical/MOM_diabatic_driver.F90 +++ b/src/parameterizations/vertical/MOM_diabatic_driver.F90 @@ -249,9 +249,9 @@ module MOM_diabatic_driver real, allocatable, dimension(:,:,:) :: KPP_NLTscalar !< KPP non-local transport for scalars [nondim] real, allocatable, dimension(:,:,:) :: KPP_buoy_flux !< KPP forcing buoyancy flux [L2 T-3 ~> m2 s-3] real, allocatable, dimension(:,:) :: KPP_temp_flux !< KPP effective temperature flux - !! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] + !! [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] real, allocatable, dimension(:,:) :: KPP_salt_flux !< KPP effective salt flux - !! [ppt H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] + !! [S H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] type(time_type), pointer :: Time !< Pointer to model time (needed for sponges) end type diabatic_CS @@ -298,13 +298,13 @@ subroutine diabatic(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Time_end, & eta ! Interface heights before diapycnal mixing [Z ~> m] real, dimension(SZI_(G),SZJ_(G),CS%nMode) :: & cn_IGW ! baroclinic internal gravity wave speeds [L T-1 ~> m s-1] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: temp_diag ! Previous temperature for diagnostics [degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: temp_diag ! Previous temperature for diagnostics [C ~> degC] integer :: i, j, k, m, is, ie, js, je, nz logical :: showCallTree ! If true, show the call tree real, allocatable, dimension(:,:,:) :: h_in ! thickness before thermodynamics [H ~> m or kg m-2] - real, allocatable, dimension(:,:,:) :: t_in ! temperature before thermodynamics [degC] - real, allocatable, dimension(:,:,:) :: s_in ! salinity before thermodynamics [ppt] + real, allocatable, dimension(:,:,:) :: t_in ! temperature before thermodynamics [C ~> degC] + real, allocatable, dimension(:,:,:) :: s_in ! salinity before thermodynamics [S ~> ppt] if (GV%ke == 1) return @@ -516,13 +516,13 @@ subroutine diabatic_ALE_legacy(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Tim ! local variables real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: & h_orig, & ! Initial layer thicknesses [H ~> m or kg m-2] - dSV_dT, & ! The partial derivative of specific volume with temperature [R-1 degC-1 ~> m3 kg-1 degC-1] - dSV_dS, & ! The partial derivative of specific volume with salinity [R-1 ppt-1 ~> m3 kg-1 ppt-1]. + dSV_dT, & ! The partial derivative of specific volume with temperature [R-1 C-1 ~> m3 kg-1 degC-1] + dSV_dS, & ! The partial derivative of specific volume with salinity [R-1 S-1 ~> m3 kg-1 ppt-1]. cTKE, & ! convective TKE requirements for each layer [R Z3 T-2 ~> J m-2]. u_h, & ! Zonal velocities interpolated to thickness points [L T-1 ~> m s-1] v_h, & ! Meridional velocities interpolated to thickness points [L T-1 ~> m s-1] - temp_diag, & ! Diagnostic array of previous temperatures [degC] - saln_diag ! Diagnostic array of previous salinity [ppt] + temp_diag, & ! Diagnostic array of previous temperatures [C ~> degC] + saln_diag ! Diagnostic array of previous salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: & ent_s, & ! The diffusive coupling across interfaces within one time step for @@ -537,8 +537,8 @@ subroutine diabatic_ALE_legacy(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Tim Kd_extra_S , & ! The extra diffusivity of salinity due to double diffusion relative to ! Kd_int [Z2 T-1 ~> m2 s-1]. Kd_ePBL, & ! test array of diapycnal diffusivities at interfaces [Z2 T-1 ~> m2 s-1] - Tdif_flx, & ! diffusive diapycnal heat flux across interfaces [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] - Sdif_flx ! diffusive diapycnal salt flux across interfaces [ppt H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] + Tdif_flx, & ! diffusive diapycnal heat flux across interfaces [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] + Sdif_flx ! diffusive diapycnal salt flux across interfaces [S H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] real, dimension(SZI_(G),SZJ_(G)) :: & SkinBuoyFlux ! 2d surface buoyancy flux [Z2 T-3 ~> m2 s-3], used by ePBL @@ -703,8 +703,10 @@ subroutine diabatic_ALE_legacy(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Tim call MOM_thermovar_chksum("after KPP", tv, G, US) call hchksum(Kd_heat, "after KPP Kd_heat", G%HI, haloshift=0, scale=US%Z2_T_to_m2_s) call hchksum(Kd_salt, "after KPP Kd_salt", G%HI, haloshift=0, scale=US%Z2_T_to_m2_s) - call hchksum(CS%KPP_temp_flux, "before KPP_applyNLT netHeat", G%HI, haloshift=0, scale=GV%H_to_m*US%s_to_T) - call hchksum(CS%KPP_salt_flux, "before KPP_applyNLT netSalt", G%HI, haloshift=0, scale=GV%H_to_m*US%s_to_T) + call hchksum(CS%KPP_temp_flux, "before KPP_applyNLT netHeat", G%HI, haloshift=0, & + scale=US%C_to_degC*GV%H_to_m*US%s_to_T) + call hchksum(CS%KPP_salt_flux, "before KPP_applyNLT netSalt", G%HI, haloshift=0, & + scale=US%S_to_ppt*GV%H_to_m*US%s_to_T) call hchksum(CS%KPP_NLTheat, "before KPP_applyNLT NLTheat", G%HI, haloshift=0) call hchksum(CS%KPP_NLTscalar, "before KPP_applyNLT NLTscalar", G%HI, haloshift=0) endif @@ -801,8 +803,10 @@ subroutine diabatic_ALE_legacy(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Tim call hchksum(ent_s, "after applyBoundaryFluxes ent_s", G%HI, haloshift=0, scale=GV%H_to_m) call hchksum(cTKE, "after applyBoundaryFluxes cTKE", G%HI, haloshift=0, & scale=US%RZ3_T3_to_W_m2*US%T_to_s) - call hchksum(dSV_dT, "after applyBoundaryFluxes dSV_dT", G%HI, haloshift=0, scale=US%kg_m3_to_R) - call hchksum(dSV_dS, "after applyBoundaryFluxes dSV_dS", G%HI, haloshift=0, scale=US%kg_m3_to_R) + call hchksum(dSV_dT, "after applyBoundaryFluxes dSV_dT", G%HI, haloshift=0, & + scale=US%kg_m3_to_R*US%degC_to_C) + call hchksum(dSV_dS, "after applyBoundaryFluxes dSV_dS", G%HI, haloshift=0, & + scale=US%kg_m3_to_R*US%ppt_to_S) endif call find_uv_at_h(u, v, h, u_h, v_h, G, GV, US) @@ -1097,13 +1101,13 @@ subroutine diabatic_ALE(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Time_end, ! local variables real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: & h_orig, & ! Initial layer thicknesses [H ~> m or kg m-2] - dSV_dT, & ! The partial derivative of specific volume with temperature [R-1 degC-1 ~> m3 kg-1 degC-1] - dSV_dS, & ! The partial derivative of specific volume with salinity [R-1 ppt-1 ~> m3 kg-1 ppt-1]. + dSV_dT, & ! The partial derivative of specific volume with temperature [R-1 C-1 ~> m3 kg-1 degC-1] + dSV_dS, & ! The partial derivative of specific volume with salinity [R-1 S-1 ~> m3 kg-1 ppt-1]. cTKE, & ! convective TKE requirements for each layer [R Z3 T-2 ~> J m-2]. u_h, & ! Zonal velocities interpolated to thickness points [L T-1 ~> m s-1] v_h, & ! Meridional velocities interpolated to thickness points [L T-1 ~> m s-1] - temp_diag, & ! Diagnostic array of previous temperatures [degC] - saln_diag ! Diagnostic array of previous salinity [ppt] + temp_diag, & ! Diagnostic array of previous temperatures [C ~> degC] + saln_diag ! Diagnostic array of previous salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: & ent_s, & ! The diffusive coupling across interfaces within one time step for @@ -1118,8 +1122,8 @@ subroutine diabatic_ALE(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Time_end, Kd_extra_S , & ! The extra diffusivity of salinity due to double diffusion relative to ! Kd_int returned from set_diffusivity [Z2 T-1 ~> m2 s-1]. Kd_ePBL, & ! boundary layer or convective diapycnal diffusivities at interfaces [Z2 T-1 ~> m2 s-1] - Tdif_flx, & ! diffusive diapycnal heat flux across interfaces [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] - Sdif_flx ! diffusive diapycnal salt flux across interfaces [ppt H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] + Tdif_flx, & ! diffusive diapycnal heat flux across interfaces [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] + Sdif_flx ! diffusive diapycnal salt flux across interfaces [S H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] real, dimension(SZI_(G),SZJ_(G)) :: & SkinBuoyFlux ! 2d surface buoyancy flux [Z2 T-3 ~> m2 s-3], used by ePBL @@ -1276,8 +1280,10 @@ subroutine diabatic_ALE(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Time_end, call MOM_thermovar_chksum("after KPP", tv, G, US) call hchksum(Kd_heat, "after KPP Kd_heat", G%HI, haloshift=0, scale=US%Z2_T_to_m2_s) call hchksum(Kd_salt, "after KPP Kd_salt", G%HI, haloshift=0, scale=US%Z2_T_to_m2_s) - call hchksum(CS%KPP_temp_flux, "before KPP_applyNLT netHeat", G%HI, haloshift=0, scale=GV%H_to_m*US%s_to_T) - call hchksum(CS%KPP_salt_flux, "before KPP_applyNLT netSalt", G%HI, haloshift=0, scale=GV%H_to_m*US%s_to_T) + call hchksum(CS%KPP_temp_flux, "before KPP_applyNLT netHeat", G%HI, haloshift=0, & + scale=US%C_to_degC*GV%H_to_m*US%s_to_T) + call hchksum(CS%KPP_salt_flux, "before KPP_applyNLT netSalt", G%HI, haloshift=0, & + scale=US%S_to_ppt*GV%H_to_m*US%s_to_T) call hchksum(CS%KPP_NLTheat, "before KPP_applyNLT NLTheat", G%HI, haloshift=0) call hchksum(CS%KPP_NLTscalar, "before KPP_applyNLT NLTscalar", G%HI, haloshift=0) endif @@ -1335,8 +1341,10 @@ subroutine diabatic_ALE(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Time_end, call hchksum(ent_s, "after applyBoundaryFluxes ent_s", G%HI, haloshift=0, scale=GV%H_to_m) call hchksum(cTKE, "after applyBoundaryFluxes cTKE", G%HI, haloshift=0, & scale=US%RZ3_T3_to_W_m2*US%T_to_s) - call hchksum(dSV_dT, "after applyBoundaryFluxes dSV_dT", G%HI, haloshift=0, scale=US%kg_m3_to_R) - call hchksum(dSV_dS, "after applyBoundaryFluxes dSV_dS", G%HI, haloshift=0, scale=US%kg_m3_to_R) + call hchksum(dSV_dT, "after applyBoundaryFluxes dSV_dT", G%HI, haloshift=0, & + scale=US%kg_m3_to_R*US%degC_to_C) + call hchksum(dSV_dS, "after applyBoundaryFluxes dSV_dS", G%HI, haloshift=0, & + scale=US%kg_m3_to_R*US%ppt_to_S) endif call find_uv_at_h(u, v, h, u_h, v_h, G, GV, US) @@ -1612,8 +1620,8 @@ subroutine layered_diabatic(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Time_e ! layer thicknesses (if a mixed layer is used) [H ~> m or kg m-2] u_h, & ! Zonal velocities at thickness points after entrainment [L T-1 ~> m s-1] v_h, & ! Meridional velocities at thickness points after entrainment [L T-1 ~> m s-1] - temp_diag, & ! Diagnostic array of previous temperatures [degC] - saln_diag ! Diagnostic array of previous salinity [ppt] + temp_diag, & ! Diagnostic array of previous temperatures [C ~> degC] + saln_diag ! Diagnostic array of previous salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G)) :: & Rcv_ml ! Coordinate density of mixed layer [R ~> kg m-3], used for applying sponges @@ -1631,10 +1639,10 @@ subroutine layered_diabatic(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Time_e ! Kd_int [Z2 T-1 ~> m2 s-1]. Kd_extra_S , & ! The extra diffusivity of salinity due to double diffusion relative to ! Kd_int [Z2 T-1 ~> m2 s-1]. - Tdif_flx, & ! diffusive diapycnal heat flux across interfaces [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] - Tadv_flx, & ! advective diapycnal heat flux across interfaces [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1] - Sdif_flx, & ! diffusive diapycnal salt flux across interfaces [ppt H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] - Sadv_flx ! advective diapycnal salt flux across interfaces [ppt H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] + Tdif_flx, & ! diffusive diapycnal heat flux across interfaces [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] + Tadv_flx, & ! advective diapycnal heat flux across interfaces [C H T-1 ~> degC m s-1 or degC kg m-2 s-1] + Sdif_flx, & ! diffusive diapycnal salt flux across interfaces [S H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] + Sadv_flx ! advective diapycnal salt flux across interfaces [S H T-1 ~> ppt m s-1 or ppt kg m-2 s-1] ! The following 3 variables are only used with a bulk mixed layer. real, pointer, dimension(:,:,:) :: & @@ -1892,8 +1900,10 @@ subroutine layered_diabatic(u, v, h, tv, Hml, fluxes, visc, ADp, CDp, dt, Time_e if (CS%useKPP) then call cpu_clock_begin(id_clock_kpp) if (CS%debug) then - call hchksum(CS%KPP_temp_flux, "before KPP_applyNLT netHeat", G%HI, haloshift=0, scale=GV%H_to_m*US%s_to_T) - call hchksum(CS%KPP_salt_flux, "before KPP_applyNLT netSalt", G%HI, haloshift=0, scale=GV%H_to_m*US%s_to_T) + call hchksum(CS%KPP_temp_flux, "before KPP_applyNLT netHeat", G%HI, haloshift=0, & + scale=US%C_to_degC*GV%H_to_m*US%s_to_T) + call hchksum(CS%KPP_salt_flux, "before KPP_applyNLT netSalt", G%HI, haloshift=0, & + scale=US%S_to_ppt*GV%H_to_m*US%s_to_T) call hchksum(CS%KPP_NLTheat, "before KPP_applyNLT NLTheat", G%HI, haloshift=0) call hchksum(CS%KPP_NLTscalar, "before KPP_applyNLT NLTscalar", G%HI, haloshift=0) endif @@ -2588,8 +2598,9 @@ subroutine diagnose_diabatic_diff_tendency(tv, h, temp_old, saln_old, dt, G, GV, type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure type(thermo_var_ptrs), intent(in) :: tv !< points to updated thermodynamic fields real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< thickness [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: temp_old !< temperature prior to diabatic physics - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: saln_old !< salinity prior to diabatic physics [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: temp_old !< temperature prior to diabatic + !! physics [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: saln_old !< salinity prior to diabatic physics [S ~> ppt] real, intent(in) :: dt !< time step [T ~> s] type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(diabatic_CS), pointer :: CS !< module control structure @@ -2598,7 +2609,7 @@ subroutine diagnose_diabatic_diff_tendency(tv, h, temp_old, saln_old, dt, G, GV, real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: work_3d real, dimension(SZI_(G),SZJ_(G)) :: work_2d real :: Idt ! The inverse of the timestep [T-1 ~> s-1] - real :: ppt2mks = 0.001 ! Conversion factor from g/kg to kg/kg. + real :: ppt2mks ! Conversion factor from S to kg/kg [S-1 ~> ppt-1]. integer :: i, j, k, is, ie, js, je, nz logical :: do_saln_tend ! Calculate salinity-based tendency diagnostics @@ -2648,6 +2659,7 @@ subroutine diagnose_diabatic_diff_tendency(tv, h, temp_old, saln_old, dt, G, GV, ! salt tendency if (CS%id_diabatic_diff_salt_tend > 0 .or. CS%id_diabatic_diff_salt_tend_2d > 0) then + ppt2mks = US%S_to_ppt*0.001 do k=1,nz ; do j=js,je ; do i=is,ie work_3d(i,j,k) = h(i,j,k)*GV%H_to_RZ * ppt2mks * work_3d(i,j,k) enddo ; enddo ; enddo @@ -2679,9 +2691,9 @@ subroutine diagnose_boundary_forcing_tendency(tv, h, temp_old, saln_old, h_old, real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: h !< thickness after boundary flux application [H ~> m or kg m-2] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(in) :: temp_old !< temperature prior to boundary flux application [degC] + intent(in) :: temp_old !< temperature prior to boundary flux application [C ~> degC] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(in) :: saln_old !< salinity prior to boundary flux application [ppt] + intent(in) :: saln_old !< salinity prior to boundary flux application [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: h_old !< thickness prior to boundary flux application [H ~> m or kg m-2] real, intent(in) :: dt !< time step [T ~> s] @@ -2692,7 +2704,7 @@ subroutine diagnose_boundary_forcing_tendency(tv, h, temp_old, saln_old, h_old, real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: work_3d real, dimension(SZI_(G),SZJ_(G)) :: work_2d real :: Idt ! The inverse of the timestep [T-1 ~> s-1] - real :: ppt2mks = 0.001 ! Conversion factor from g/kg to kg/kg. + real :: ppt2mks ! Conversion factor from S to kg/kg [S-1 ~> ppt-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 @@ -2743,6 +2755,7 @@ subroutine diagnose_boundary_forcing_tendency(tv, h, temp_old, saln_old, h_old, ! salt tendency if (CS%id_boundary_forcing_salt_tend > 0 .or. CS%id_boundary_forcing_salt_tend_2d > 0) then + ppt2mks = US%S_to_ppt*0.001 do k=1,nz ; do j=js,je ; do i=is,ie work_3d(i,j,k) = GV%H_to_RZ * ppt2mks * Idt * (h(i,j,k) * tv%S(i,j,k) - h_old(i,j,k) * saln_old(i,j,k)) enddo ; enddo ; enddo @@ -2770,7 +2783,7 @@ subroutine diagnose_frazil_tendency(tv, h, temp_old, dt, G, GV, US, CS) type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure type(thermo_var_ptrs), intent(in) :: tv !< points to updated thermodynamic fields real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< thickness [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: temp_old !< temperature prior to frazil formation [degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: temp_old !< temperature prior to frazil formation [C ~> degC] real, intent(in) :: dt !< time step [T ~> s] type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(diabatic_CS), pointer :: CS !< module control structure @@ -3118,19 +3131,19 @@ subroutine diabatic_driver_init(Time, G, GV, US, param_file, useALEalgorithm, di if (use_temperature) then CS%id_Tdif = register_diag_field('ocean_model',"Tflx_dia_diff", diag%axesTi, & Time, "Diffusive diapycnal temperature flux across interfaces", & - "degC m s-1", conversion=GV%H_to_m*US%s_to_T) + "degC m s-1", conversion=US%C_to_degC*GV%H_to_m*US%s_to_T) if (.not.CS%useALEalgorithm) then CS%id_Tadv = register_diag_field('ocean_model',"Tflx_dia_adv", diag%axesTi, & Time, "Advective diapycnal temperature flux across interfaces", & - "degC m s-1", conversion=GV%H_to_m*US%s_to_T) + "degC m s-1", conversion=US%C_to_degC*GV%H_to_m*US%s_to_T) endif CS%id_Sdif = register_diag_field('ocean_model',"Sflx_dia_diff", diag%axesTi, & Time, "Diffusive diapycnal salnity flux across interfaces", & - "psu m s-1", conversion=GV%H_to_m*US%s_to_T) + "psu m s-1", conversion=US%S_to_ppt*GV%H_to_m*US%s_to_T) if (.not.CS%useALEalgorithm) then CS%id_Sadv = register_diag_field('ocean_model',"Sflx_dia_adv", diag%axesTi, & Time, "Advective diapycnal salnity flux across interfaces", & - "psu m s-1", conversion=GV%H_to_m*US%s_to_T) + "psu m s-1", conversion=US%S_to_ppt*GV%H_to_m*US%s_to_T) endif CS%id_MLD_003 = register_diag_field('ocean_model', 'MLD_003', diag%axesT1, Time, & 'Mixed layer depth (delta rho = 0.03)', 'm', conversion=US%Z_to_m, & @@ -3191,9 +3204,9 @@ subroutine diabatic_driver_init(Time, G, GV, US, param_file, useALEalgorithm, di 'Interface Heights before diabatic forcing', 'm', conversion=US%Z_to_m) if (use_temperature) then CS%id_T_predia = register_diag_field('ocean_model', 'temp_predia', diag%axesTL, Time, & - 'Potential Temperature', 'degC') + 'Potential Temperature', 'degC', conversion=US%C_to_degC) CS%id_S_predia = register_diag_field('ocean_model', 'salt_predia', diag%axesTL, Time, & - 'Salinity', 'PSU') + 'Salinity', 'PSU', conversion=US%S_to_ppt) endif CS%id_Kd_int = register_diag_field('ocean_model', 'Kd_interface', diag%axesTi, Time, & @@ -3235,14 +3248,14 @@ subroutine diabatic_driver_init(Time, G, GV, US, param_file, useALEalgorithm, di if (CS%useALEalgorithm) then CS%id_diabatic_diff_temp_tend = register_diag_field('ocean_model', & 'diabatic_diff_temp_tendency', diag%axesTL, Time, & - 'Diabatic diffusion temperature tendency', 'degC s-1', conversion=US%s_to_T) + 'Diabatic diffusion temperature tendency', 'degC s-1', conversion=US%C_to_degC*US%s_to_T) if (CS%id_diabatic_diff_temp_tend > 0) then CS%diabatic_diff_tendency_diag = .true. endif CS%id_diabatic_diff_saln_tend = register_diag_field('ocean_model',& 'diabatic_diff_saln_tendency', diag%axesTL, Time, & - 'Diabatic diffusion salinity tendency', 'psu s-1', conversion=US%s_to_T) + 'Diabatic diffusion salinity tendency', 'psu s-1', conversion=US%S_to_ppt*US%s_to_T) if (CS%id_diabatic_diff_saln_tend > 0) then CS%diabatic_diff_tendency_diag = .true. endif @@ -3315,14 +3328,14 @@ subroutine diabatic_driver_init(Time, G, GV, US, param_file, useALEalgorithm, di CS%id_boundary_forcing_temp_tend = register_diag_field('ocean_model',& 'boundary_forcing_temp_tendency', diag%axesTL, Time, & - 'Boundary forcing temperature tendency', 'degC s-1', conversion=US%s_to_T) + 'Boundary forcing temperature tendency', 'degC s-1', conversion=US%C_to_degC*US%s_to_T) if (CS%id_boundary_forcing_temp_tend > 0) then CS%boundary_forcing_tendency_diag = .true. endif CS%id_boundary_forcing_saln_tend = register_diag_field('ocean_model',& 'boundary_forcing_saln_tendency', diag%axesTL, Time, & - 'Boundary forcing saln tendency', 'psu s-1', conversion=US%s_to_T) + 'Boundary forcing saln tendency', 'psu s-1', conversion=US%S_to_ppt*US%s_to_T) if (CS%id_boundary_forcing_saln_tend > 0) then CS%boundary_forcing_tendency_diag = .true. endif @@ -3370,7 +3383,7 @@ subroutine diabatic_driver_init(Time, G, GV, US, param_file, useALEalgorithm, di ! diagnostic for tendency of temp due to frazil CS%id_frazil_temp_tend = register_diag_field('ocean_model',& 'frazil_temp_tendency', diag%axesTL, Time, & - 'Temperature tendency due to frazil formation', 'degC s-1', conversion=US%s_to_T) + 'Temperature tendency due to frazil formation', 'degC s-1', conversion=US%C_to_degC*US%s_to_T) if (CS%id_frazil_temp_tend > 0) then CS%frazil_tendency_diag = .true. endif diff --git a/src/parameterizations/vertical/MOM_diapyc_energy_req.F90 b/src/parameterizations/vertical/MOM_diapyc_energy_req.F90 index f55f1e27a5..c2e05dc930 100644 --- a/src/parameterizations/vertical/MOM_diapyc_energy_req.F90 +++ b/src/parameterizations/vertical/MOM_diapyc_energy_req.F90 @@ -62,7 +62,7 @@ subroutine diapyc_energy_req_test(h_3d, dt, tv, G, GV, US, CS, Kd_int) ! Local variables real, dimension(GV%ke) :: & - T0, S0, & ! T0 & S0 are columns of initial temperatures and salinities [degC] and g/kg. + T0, S0, & ! T0 & S0 are columns of initial temperatures and salinities [C ~> degC] and [S ~> ppt]. h_col ! h_col is a column of thicknesses h at tracer points [H ~> m or kg m-2]. real, dimension(GV%ke+1) :: & Kd, & ! A column of diapycnal diffusivities at interfaces [Z2 T-1 ~> m2 s-1]. @@ -127,8 +127,8 @@ subroutine diapyc_energy_req_calc(h_in, T_in, S_in, Kd, energy_Kd, dt, tv, & type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type real, dimension(GV%ke), intent(in) :: h_in !< Layer thickness before entrainment, !! [H ~> m or kg m-2]. - real, dimension(GV%ke), intent(in) :: T_in !< The layer temperatures [degC]. - real, dimension(GV%ke), intent(in) :: S_in !< The layer salinities [ppt]. + real, dimension(GV%ke), intent(in) :: T_in !< The layer temperatures [C ~> degC]. + real, dimension(GV%ke), intent(in) :: S_in !< The layer salinities [S ~> ppt]. real, dimension(GV%ke+1), intent(in) :: Kd !< The interfaces diapycnal diffusivities !! [Z2 T-1 ~> m2 s-1]. real, intent(in) :: dt !< The amount of time covered by this call [T ~> s]. @@ -151,40 +151,40 @@ subroutine diapyc_energy_req_calc(h_in, T_in, S_in, Kd, energy_Kd, dt, tv, & real, dimension(GV%ke) :: & p_lay, & ! Average pressure of a layer [R L2 T-2 ~> Pa]. - dSV_dT, & ! Partial derivative of specific volume with temperature [R-1 degC-1 ~> m3 kg-1 degC-1]. - dSV_dS, & ! Partial derivative of specific volume with salinity [R-1 ppt-1 ~> m3 kg-1 ppt-1]. - T0, S0, & ! Initial temperatures and salinities [degC] and [ppt]. - Te, Se, & ! Running incomplete estimates of the new temperatures and salinities [degC] and [ppt]. - Te_a, Se_a, & ! Running incomplete estimates of the new temperatures and salinities [degC] and [ppt]. - Te_b, Se_b, & ! Running incomplete estimates of the new temperatures and salinities [degC] and [ppt]. - Tf, Sf, & ! New final values of the temperatures and salinities [degC] and [ppt]. - dTe, dSe, & ! Running (1-way) estimates of temperature and salinity change [degC] and [ppt]. + dSV_dT, & ! Partial derivative of specific volume with temperature [R-1 C-1 ~> m3 kg-1 degC-1]. + dSV_dS, & ! Partial derivative of specific volume with salinity [R-1 S-1 ~> m3 kg-1 ppt-1]. + T0, S0, & ! Initial temperatures and salinities [C ~> degC] and [S ~> ppt]. + Te, Se, & ! Running incomplete estimates of the new temperatures and salinities [C ~> degC] and [S ~> ppt] + Te_a, Se_a, & ! Running incomplete estimates of the new temperatures and salinities [C ~> degC] and [S ~> ppt] + Te_b, Se_b, & ! Running incomplete estimates of the new temperatures and salinities [C ~> degC] and [S ~> ppt] + Tf, Sf, & ! New final values of the temperatures and salinities [C ~> degC] and [S ~> ppt]. + dTe, dSe, & ! Running (1-way) estimates of temperature and salinity change [C ~> degC] and [S ~> ppt]. Th_a, & ! An effective temperature times a thickness in the layer above, including implicit - ! mixing effects with other yet higher layers [degC H ~> degC m or degC kg m-2]. + ! mixing effects with other yet higher layers [C H ~> degC m or degC kg m-2]. Sh_a, & ! An effective salinity times a thickness in the layer above, including implicit - ! mixing effects with other yet higher layers [ppt H ~> ppt m or ppt kg m-2]. + ! mixing effects with other yet higher layers [S H ~> ppt m or ppt kg m-2]. Th_b, & ! An effective temperature times a thickness in the layer below, including implicit - ! mixing effects with other yet lower layers [degC H ~> degC m or degC kg m-2]. + ! mixing effects with other yet lower layers [C H ~> degC m or degC kg m-2]. Sh_b, & ! An effective salinity times a thickness in the layer below, including implicit - ! mixing effects with other yet lower layers [ppt H ~> ppt m or ppt kg m-2]. + ! mixing effects with other yet lower layers [S H ~> ppt m or ppt kg m-2]. dT_to_dPE, & ! Partial derivative of column potential energy with the temperature and salinity - dS_to_dPE, & ! changes within a layer [R Z L2 T-2 degC-1 ~> J m-2 degC-1] and [R Z L2 T-2 ppt-1 ~> J m-2 ppt-1]. + dS_to_dPE, & ! changes within a layer [R Z L2 T-2 C-1 ~> J m-2 degC-1] and [R Z L2 T-2 S-1 ~> J m-2 ppt-1] dT_to_dColHt, & ! Partial derivatives of the total column height with the temperature - dS_to_dColHt, & ! and salinity changes within a layer [Z degC-1 ~> m degC-1] and [Z ppt-1 ~> m ppt-1]. + dS_to_dColHt, & ! and salinity changes within a layer [Z C-1 ~> m degC-1] and [Z S-1 ~> m ppt-1]. dT_to_dColHt_a, & ! Partial derivatives of the total column height with the temperature dS_to_dColHt_a, & ! and salinity changes within a layer, including the implicit effects - ! of mixing with layers higher in the water colun [Z degC-1 ~> m degC-1] and [Z ppt-1 ~> m ppt-1]. + ! of mixing with layers higher in the water column [Z C-1 ~> m degC-1] and [Z S-1 ~> m ppt-1]. dT_to_dColHt_b, & ! Partial derivatives of the total column height with the temperature dS_to_dColHt_b, & ! and salinity changes within a layer, including the implicit effects - ! of mixing with layers lower in the water colun [Z degC-1 ~> m degC-1] and [Z ppt-1 ~> m ppt-1]. + ! of mixing with layers lower in the water column [Z C-1 ~> m degC-1] and [Z S-1 ~> m ppt-1]. dT_to_dPE_a, & ! Partial derivatives of column potential energy with the temperature dS_to_dPE_a, & ! and salinity changes within a layer, including the implicit effects ! of mixing with layers higher in the water column, in - ! units of [R Z L2 T-2 degC-1 ~> J m-2 degC-1] and [R Z L2 T-2 ppt-1 ~> J m-2 ppt-1]. + ! units of [R Z L2 T-2 C-1 ~> J m-2 degC-1] and [R Z L2 T-2 S-1 ~> J m-2 ppt-1]. dT_to_dPE_b, & ! Partial derivatives of column potential energy with the temperature dS_to_dPE_b, & ! and salinity changes within a layer, including the implicit effects ! of mixing with layers lower in the water column, in - ! units of [R Z L2 T-2 degC-1 ~> J m-2 degC-1] and [R Z L2 T-2 ppt-1 ~> J m-2 ppt-1]. + ! units of [R Z L2 T-2 C-1 ~> J m-2 degC-1] and [R Z L2 T-2 S-1 ~> J m-2 ppt-1]. hp_a, & ! An effective pivot thickness of the layer including the effects ! of coupling with layers above [H ~> m or kg m-2]. This is the first term ! in the denominator of b1 in a downward-oriented tridiagonal solver. @@ -222,9 +222,9 @@ subroutine diapyc_energy_req_calc(h_in, T_in, S_in, Kd, energy_Kd, dt, tv, & real :: h_neglect ! A thickness that is so small it is usually lost ! in roundoff and can be neglected [H ~> m or kg m-2]. real :: dTe_term ! A diffusivity-independent term related to the temperature - ! change in the layer below the interface [degC H ~> degC m or degC kg m-2]. + ! change in the layer below the interface [C H ~> degC m or degC kg m-2]. real :: dSe_term ! A diffusivity-independent term related to the salinity - ! change in the layer below the interface [ppt H ~> ppt m or ppt kg m-2]. + ! change in the layer below the interface [S H ~> ppt m or ppt kg m-2]. real :: Kddt_h_guess ! A guess of the final value of Kddt_h [H ~> m or kg m-2]. real :: dMass ! The mass per unit area within a layer [R Z ~> kg m-2]. real :: dPres ! The hydrostatic pressure change across a layer [R L2 T-2 ~> Pa]. @@ -234,8 +234,10 @@ subroutine diapyc_energy_req_calc(h_in, T_in, S_in, Kd, energy_Kd, dt, tv, & real :: ColHt_cor ! The correction to PE_chg that is made due to a net ! change in the column height [R L2 Z T-2 ~> J m-2]. real :: htot ! A running sum of thicknesses [H ~> m or kg m-2]. - real :: dTe_t2, dT_km1_t2, dT_k_t2 ! Temporary arrays describing temperature changes [degC]. - real :: dSe_t2, dS_km1_t2, dS_k_t2 ! Temporary arrays describing salinity changes [ppt]. + real :: dTe_t2 ! Temporary arrays with integrated temperature changes [C H ~> degC m or degC kg m-2] + real :: dSe_t2 ! Temporary arrays with integrated salinity changes [S H ~> ppt m or ppt kg m-2] + real :: dT_km1_t2, dT_k_t2 ! Temporary arrays describing temperature changes [C ~> degC]. + real :: dS_km1_t2, dS_k_t2 ! Temporary arrays describing salinity changes [S ~> ppt]. logical :: do_print ! The following are a bunch of diagnostic arrays for debugging purposes. @@ -977,51 +979,51 @@ subroutine find_PE_chg(Kddt_h0, dKddt_h, hp_a, hp_b, Th_a, Sh_a, Th_b, Sh_b, & !! Kddt_h for the interface above [H ~> m or kg m-2]. real, intent(in) :: Th_a !< An effective temperature times a thickness in the layer !! above, including implicit mixing effects with other - !! yet higher layers [degC H ~> degC m or degC kg m-2]. + !! yet higher layers [C H ~> degC m or degC kg m-2]. real, intent(in) :: Sh_a !< An effective salinity times a thickness in the layer !! above, including implicit mixing effects with other - !! yet higher layers [ppt H ~> ppt m or ppt kg m-2]. + !! yet higher layers [S H ~> ppt m or ppt kg m-2]. real, intent(in) :: Th_b !< An effective temperature times a thickness in the layer !! below, including implicit mixing effects with other - !! yet lower layers [degC H ~> degC m or degC kg m-2]. + !! yet lower layers [C H ~> degC m or degC kg m-2]. real, intent(in) :: Sh_b !< An effective salinity times a thickness in the layer !! below, including implicit mixing effects with other - !! yet lower layers [ppt H ~> ppt m or ppt kg m-2]. + !! yet lower layers [S H ~> ppt m or ppt kg m-2]. real, intent(in) :: dT_to_dPE_a !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating !! a layer's temperature change to the change in column !! potential energy, including all implicit diffusive changes - !! in the temperatures of all the layers above [R Z L2 T-2 degC-1 ~> J m-2 degC-1]. + !! in the temperatures of all the layers above [R Z L2 T-2 C-1 ~> J m-2 degC-1]. real, intent(in) :: dS_to_dPE_a !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating !! a layer's salinity change to the change in column !! potential energy, including all implicit diffusive changes - !! in the salinities of all the layers above [R Z L2 T-2 ppt-1 ~> J m-2 ppt-1]. + !! in the salinities of all the layers above [R Z L2 T-2 S-1 ~> J m-2 ppt-1]. real, intent(in) :: dT_to_dPE_b !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating !! a layer's temperature change to the change in column !! potential energy, including all implicit diffusive changes - !! in the temperatures of all the layers below [R Z L2 T-2 degC-1 ~> J m-2 degC-1]. + !! in the temperatures of all the layers below [R Z L2 T-2 C-1 ~> J m-2 degC-1]. real, intent(in) :: dS_to_dPE_b !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating !! a layer's salinity change to the change in column !! potential energy, including all implicit diffusive changes - !! in the salinities of all the layers below [R Z L2 T-2 ppt-1 ~> J m-2 ppt-1]. + !! in the salinities of all the layers below [R Z L2 T-2 S-1 ~> J m-2 ppt-1]. real, intent(in) :: pres_Z !< The hydrostatic interface pressure, which is used to relate !! the changes in column thickness to the energy that is radiated !! as gravity waves and unavailable to drive mixing [R L2 T-2 ~> J m-3]. real, intent(in) :: dT_to_dColHt_a !< A factor (mass_lay*dSColHtc_vol/dT) relating !! a layer's temperature change to the change in column !! height, including all implicit diffusive changes - !! in the temperatures of all the layers above [Z degC-1 ~> m degC-1]. + !! in the temperatures of all the layers above [Z C-1 ~> m degC-1]. real, intent(in) :: dS_to_dColHt_a !< A factor (mass_lay*dSColHtc_vol/dS) relating !! a layer's salinity change to the change in column !! height, including all implicit diffusive changes - !! in the salinities of all the layers above [Z ppt-1 ~> m ppt-1]. + !! in the salinities of all the layers above [Z S-1 ~> m ppt-1]. real, intent(in) :: dT_to_dColHt_b !< A factor (mass_lay*dSColHtc_vol/dT) relating !! a layer's temperature change to the change in column !! height, including all implicit diffusive changes - !! in the temperatures of all the layers below [Z degC-1 ~> m degC-1]. + !! in the temperatures of all the layers below [Z C-1 ~> m degC-1]. real, intent(in) :: dS_to_dColHt_b !< A factor (mass_lay*dSColHtc_vol/dS) relating !! a layer's salinity change to the change in column !! height, including all implicit diffusive changes - !! in the salinities of all the layers below [Z ppt-1 ~> m ppt-1]. + !! in the salinities of all the layers below [Z S-1 ~> m ppt-1]. real, optional, intent(out) :: PE_chg !< The change in column potential energy from applying !! Kddt_h at the present interface [R Z L2 T-2 ~> J m-2]. @@ -1037,8 +1039,8 @@ subroutine find_PE_chg(Kddt_h0, dKddt_h, hp_a, hp_b, Th_a, Sh_a, Th_b, Sh_b, & real :: hps ! The sum of the two effective pivot thicknesses [H ~> m or kg m-2]. real :: bdt1 ! A product of the two pivot thicknesses plus a diffusive term [H2 ~> m2 or kg2 m-4]. - real :: dT_c ! The core term in the expressions for the temperature changes [degC H2 ~> degC m2 or degC kg2 m-4]. - real :: dS_c ! The core term in the expressions for the salinity changes [psu H2 ~> psu m2 or psu kg2 m-4]. + real :: dT_c ! The core term in the expressions for the temperature changes [C H2 ~> degC m2 or degC kg2 m-4]. + real :: dS_c ! The core term in the expressions for the salinity changes [S H2 ~> psu m2 or psu kg2 m-4]. real :: PEc_core ! The diffusivity-independent core term in the expressions ! for the potential energy changes [R L2 T-2 ~> J m-3]. real :: ColHt_core ! The diffusivity-independent core term in the expressions @@ -1120,48 +1122,48 @@ subroutine find_PE_chg_orig(Kddt_h, h_k, b_den_1, dTe_term, dSe_term, & !! is a fraction (determined from the tridiagonal solver) of !! Kddt_h for the interface above [H ~> m or kg m-2]. real, intent(in) :: dTe_term !< A diffusivity-independent term related to the temperature change - !! in the layer below the interface [degC H ~> degC m or degC kg m-2]. + !! in the layer below the interface [C H ~> degC m or degC kg m-2]. real, intent(in) :: dSe_term !< A diffusivity-independent term related to the salinity change - !! in the layer below the interface [ppt H ~> ppt m or ppt kg m-2]. + !! in the layer below the interface [S H ~> ppt m or ppt kg m-2]. real, intent(in) :: dT_km1_t2 !< A diffusivity-independent term related to the - !! temperature change in the layer above the interface [degC]. + !! temperature change in the layer above the interface [C ~> degC]. real, intent(in) :: dS_km1_t2 !< A diffusivity-independent term related to the - !! salinity change in the layer above the interface [ppt]. + !! salinity change in the layer above the interface [S ~> ppt]. real, intent(in) :: pres_Z !< The hydrostatic interface pressure, which is used to relate !! the changes in column thickness to the energy that is radiated !! as gravity waves and unavailable to drive mixing [R L2 T-2 ~> J m-3]. real, intent(in) :: dT_to_dPE_k !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating !! a layer's temperature change to the change in column !! potential energy, including all implicit diffusive changes - !! in the temperatures of all the layers below [R Z L2 T-2 degC-1 ~> J m-2 degC-1]. + !! in the temperatures of all the layers below [R Z L2 T-2 C-1 ~> J m-2 degC-1]. real, intent(in) :: dS_to_dPE_k !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating !! a layer's salinity change to the change in column !! potential energy, including all implicit diffusive changes - !! in the salinities of all the layers below [R Z L2 T-2 ppt-1 ~> J m-2 ppt-1]. + !! in the salinities of all the layers below [R Z L2 T-2 S-1 ~> J m-2 ppt-1]. real, intent(in) :: dT_to_dPEa !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating !! a layer's temperature change to the change in column !! potential energy, including all implicit diffusive changes - !! in the temperatures of all the layers above [R Z L2 T-2 degC-1 ~> J m-2 degC-1]. + !! in the temperatures of all the layers above [R Z L2 T-2 C-1 ~> J m-2 degC-1]. real, intent(in) :: dS_to_dPEa !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating !! a layer's salinity change to the change in column !! potential energy, including all implicit diffusive changes - !! in the salinities of all the layers above [R Z L2 T-2 ppt-1 ~> J m-2 ppt-1]. + !! in the salinities of all the layers above [R Z L2 T-2 S-1 ~> J m-2 ppt-1]. real, intent(in) :: dT_to_dColHt_k !< A factor (mass_lay*dSColHtc_vol/dT) relating !! a layer's temperature change to the change in column !! height, including all implicit diffusive changes - !! in the temperatures of all the layers below [Z degC-1 ~> m degC-1]. + !! in the temperatures of all the layers below [Z C-1 ~> m degC-1]. real, intent(in) :: dS_to_dColHt_k !< A factor (mass_lay*dSColHtc_vol/dS) relating !! a layer's salinity change to the change in column !! height, including all implicit diffusive changes - !! in the salinities of all the layers below [Z ppt-1 ~> m ppt-1]. + !! in the salinities of all the layers below [Z S-1 ~> m ppt-1]. real, intent(in) :: dT_to_dColHta !< A factor (mass_lay*dSColHtc_vol/dT) relating !! a layer's temperature change to the change in column !! height, including all implicit diffusive changes - !! in the temperatures of all the layers above [Z degC-1 ~> m degC-1]. + !! in the temperatures of all the layers above [Z C-1 ~> m degC-1]. real, intent(in) :: dS_to_dColHta !< A factor (mass_lay*dSColHtc_vol/dS) relating !! a layer's salinity change to the change in column !! height, including all implicit diffusive changes - !! in the salinities of all the layers above [Z ppt-1 ~> m ppt-1]. + !! in the salinities of all the layers above [Z S-1 ~> m ppt-1]. real, optional, intent(out) :: PE_chg !< The change in column potential energy from applying !! Kddt_h at the present interface [R Z L2 T-2 ~> J m-2]. @@ -1187,14 +1189,14 @@ subroutine find_PE_chg_orig(Kddt_h, h_k, b_den_1, dTe_term, dSe_term, & real :: ColHt_chg ! The change in column thickness [Z ~> m]. real :: dColHt_max ! The change in column thickness for infinite diffusivity [Z ~> m]. real :: dColHt_dKd ! The partial derivative of column thickness with Kddt_h [Z H-1 ~> nondim or m3 kg-1] - real :: dT_k, dT_km1 ! Temperature changes in layers k and k-1 [degC] - real :: dS_k, dS_km1 ! Salinity changes in layers k and k-1 [ppt] + real :: dT_k, dT_km1 ! Temperature changes in layers k and k-1 [C ~> degC] + real :: dS_k, dS_km1 ! Salinity changes in layers k and k-1 [S ~> ppt] real :: I_Kr_denom ! Temporary array [H-2 ~> m-2 or m4 kg-2] real :: dKr_dKd ! Temporary array [H-2 ~> m-2 or m4 kg-2] real :: ddT_k_dKd, ddT_km1_dKd ! Temporary arrays indicating the temperature changes - ! per unit change in Kddt_h [degC H-1 ~> degC m-1 or degC m2 kg-1] + ! per unit change in Kddt_h [C H-1 ~> degC m-1 or degC m2 kg-1] real :: ddS_k_dKd, ddS_km1_dKd ! Temporary arrays indicating the salinity changes - ! per unit change in Kddt_h [ppt H-1 ~> ppt m-1 or ppt m2 kg-1] + ! per unit change in Kddt_h [S H-1 ~> ppt m-1 or ppt m2 kg-1] b1 = 1.0 / (b_den_1 + Kddt_h) b1Kd = Kddt_h*b1 @@ -1327,13 +1329,13 @@ subroutine diapyc_energy_req_init(Time, G, GV, US, param_file, diag, CS) "Column Height Correction to Energy Requirements, halves", & "J m-2", conversion=US%RZ_to_kg_m2*US%L_T_to_m_s**2) CS%id_T0 = register_diag_field('ocean_model', 'EnReqTest_T0', diag%axesZL, Time, & - "Temperature before mixing", "deg C") + "Temperature before mixing", "deg C", conversion=US%C_to_degC) CS%id_Tf = register_diag_field('ocean_model', 'EnReqTest_Tf', diag%axesZL, Time, & - "Temperature after mixing", "deg C") + "Temperature after mixing", "deg C", conversion=US%C_to_degC) CS%id_S0 = register_diag_field('ocean_model', 'EnReqTest_S0', diag%axesZL, Time, & - "Salinity before mixing", "g kg-1") + "Salinity before mixing", "g kg-1", conversion=US%S_to_ppt) CS%id_Sf = register_diag_field('ocean_model', 'EnReqTest_Sf', diag%axesZL, Time, & - "Salinity after mixing", "g kg-1") + "Salinity after mixing", "g kg-1", conversion=US%S_to_ppt) CS%id_N2_0 = register_diag_field('ocean_model', 'EnReqTest_N2_0', diag%axesZi, Time, & "Squared buoyancy frequency before mixing", "second-2", conversion=US%s_to_T**2) CS%id_N2_f = register_diag_field('ocean_model', 'EnReqTest_N2_f', diag%axesZi, Time, & diff --git a/src/parameterizations/vertical/MOM_energetic_PBL.F90 b/src/parameterizations/vertical/MOM_energetic_PBL.F90 index c12921b1d9..07fd69d744 100644 --- a/src/parameterizations/vertical/MOM_energetic_PBL.F90 +++ b/src/parameterizations/vertical/MOM_energetic_PBL.F90 @@ -260,10 +260,10 @@ subroutine energetic_PBL(h_3d, u_3d, v_3d, tv, fluxes, dt, Kd_int, G, GV, US, CS real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: dSV_dT !< The partial derivative of in-situ specific !! volume with potential temperature - !! [R-1 degC-1 ~> m3 kg-1 degC-1]. + !! [R-1 C-1 ~> m3 kg-1 degC-1]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: dSV_dS !< The partial derivative of in-situ specific - !! volume with salinity [R-1 ppt-1 ~> m3 kg-1 ppt-1]. + !! volume with salinity [R-1 S-1 ~> m3 kg-1 ppt-1]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: TKE_forced !< The forcing requirements to homogenize the !! forcing that has been applied to each layer @@ -309,21 +309,21 @@ subroutine energetic_PBL(h_3d, u_3d, v_3d, tv, fluxes, dt, Kd_int, G, GV, US, CS ! Local variables real, dimension(SZI_(G),SZK_(GV)) :: & h_2d, & ! A 2-d slice of the layer thickness [H ~> m or kg m-2]. - T_2d, & ! A 2-d slice of the layer temperatures [degC]. - S_2d, & ! A 2-d slice of the layer salinities [ppt]. + T_2d, & ! A 2-d slice of the layer temperatures [C ~> degC]. + S_2d, & ! A 2-d slice of the layer salinities [S ~> ppt]. TKE_forced_2d, & ! A 2-d slice of TKE_forced [R Z3 T-2 ~> J m-2]. - dSV_dT_2d, & ! A 2-d slice of dSV_dT [R-1 degC-1 ~> m3 kg-1 degC-1]. - dSV_dS_2d, & ! A 2-d slice of dSV_dS [R-1 ppt-1 ~> m3 kg-1 ppt-1]. + dSV_dT_2d, & ! A 2-d slice of dSV_dT [R-1 C-1 ~> m3 kg-1 degC-1]. + dSV_dS_2d, & ! A 2-d slice of dSV_dS [R-1 S-1 ~> m3 kg-1 ppt-1]. u_2d, & ! A 2-d slice of the zonal velocity [L T-1 ~> m s-1]. v_2d ! A 2-d slice of the meridional velocity [L T-1 ~> m s-1]. real, dimension(SZI_(G),SZK_(GV)+1) :: & Kd_2d ! A 2-d version of the diapycnal diffusivity [Z2 T-1 ~> m2 s-1]. real, dimension(SZK_(GV)) :: & h, & ! The layer thickness [H ~> m or kg m-2]. - T0, & ! The initial layer temperatures [degC]. - S0, & ! The initial layer salinities [ppt]. - dSV_dT_1d, & ! The partial derivatives of specific volume with temperature [R-1 degC-1 ~> m3 kg-1 degC-1]. - dSV_dS_1d, & ! The partial derivatives of specific volume with salinity [R-1 ppt-1 ~> m3 kg-1 ppt-1]. + T0, & ! The initial layer temperatures [C ~> degC]. + S0, & ! The initial layer salinities [S ~> ppt]. + dSV_dT_1d, & ! The partial derivatives of specific volume with temperature [R-1 C-1 ~> m3 kg-1 degC-1]. + dSV_dS_1d, & ! The partial derivatives of specific volume with salinity [R-1 S-1 ~> m3 kg-1 ppt-1]. TKE_forcing, & ! Forcing of the TKE in the layer coming from TKE_forced [R Z3 T-2 ~> J m-2]. u, & ! The zonal velocity [L T-1 ~> m s-1]. v ! The meridional velocity [L T-1 ~> m s-1]. @@ -509,14 +509,14 @@ subroutine ePBL_column(h, u, v, T0, S0, dSV_dT, dSV_dS, TKE_forcing, B_flux, abs !! [L T-1 ~> m s-1]. real, dimension(SZK_(GV)), intent(in) :: v !< Zonal velocities interpolated to h points !! [L T-1 ~> m s-1]. - real, dimension(SZK_(GV)), intent(in) :: T0 !< The initial layer temperatures [degC]. - real, dimension(SZK_(GV)), intent(in) :: S0 !< The initial layer salinities [ppt]. + real, dimension(SZK_(GV)), intent(in) :: T0 !< The initial layer temperatures [C ~> degC]. + real, dimension(SZK_(GV)), intent(in) :: S0 !< The initial layer salinities [S ~> ppt]. real, dimension(SZK_(GV)), intent(in) :: dSV_dT !< The partial derivative of in-situ specific !! volume with potential temperature - !! [R-1 degC-1 ~> m3 kg-1 degC-1]. + !! [R-1 C-1 ~> m3 kg-1 degC-1]. real, dimension(SZK_(GV)), intent(in) :: dSV_dS !< The partial derivative of in-situ specific - !! volume with salinity [R-1 ppt-1 ~> m3 kg-1 ppt-1]. + !! volume with salinity [R-1 S-1 ~> m3 kg-1 ppt-1]. real, dimension(SZK_(GV)), intent(in) :: TKE_forcing !< The forcing requirements to homogenize the !! forcing that has been applied to each layer !! [R Z3 T-2 ~> J m-2]. @@ -577,38 +577,38 @@ subroutine ePBL_column(h, u, v, T0, S0, dSV_dT, dSV_dS, TKE_forcing, B_flux, abs real, dimension(SZK_(GV)) :: & dT_to_dColHt, & ! Partial derivative of the total column height with the temperature changes - ! within a layer [Z degC-1 ~> m degC-1]. + ! within a layer [Z C-1 ~> m degC-1]. dS_to_dColHt, & ! Partial derivative of the total column height with the salinity changes - ! within a layer [Z ppt-1 ~> m ppt-1]. + ! within a layer [Z S-1 ~> m ppt-1]. dT_to_dPE, & ! Partial derivatives of column potential energy with the temperature - ! changes within a layer, in [R Z3 T-2 degC-1 ~> J m-2 degC-1]. + ! changes within a layer, in [R Z3 T-2 C-1 ~> J m-2 degC-1]. dS_to_dPE, & ! Partial derivatives of column potential energy with the salinity changes - ! within a layer, in [R Z3 T-2 ppt-1 ~> J m-2 ppt-1]. + ! within a layer, in [R Z3 T-2 S-1 ~> J m-2 ppt-1]. dT_to_dColHt_a, & ! Partial derivative of the total column height with the temperature changes ! within a layer, including the implicit effects of mixing with layers higher - ! in the water column [Z degC-1 ~> m degC-1]. + ! in the water column [Z C-1 ~> m degC-1]. dS_to_dColHt_a, & ! Partial derivative of the total column height with the salinity changes ! within a layer, including the implicit effects of mixing with layers higher - ! in the water column [Z ppt-1 ~> m ppt-1]. + ! in the water column [Z S-1 ~> m ppt-1]. dT_to_dPE_a, & ! Partial derivatives of column potential energy with the temperature changes ! within a layer, including the implicit effects of mixing with layers higher - ! in the water column [R Z3 T-2 degC-1 ~> J m-2 degC-1]. + ! in the water column [R Z3 T-2 C-1 ~> J m-2 degC-1]. dS_to_dPE_a, & ! Partial derivative of column potential energy with the salinity changes ! within a layer, including the implicit effects of mixing with layers higher - ! in the water column [R Z3 T-2 ppt-1 ~> J m-2 ppt-1]. + ! in the water column [R Z3 T-2 S-1 ~> J m-2 ppt-1]. c1, & ! c1 is used by the tridiagonal solver [nondim]. - Te, & ! Estimated final values of T in the column [degC]. - Se, & ! Estimated final values of S in the column [ppt]. - dTe, & ! Running (1-way) estimates of temperature change [degC]. - dSe, & ! Running (1-way) estimates of salinity change [ppt]. + Te, & ! Estimated final values of T in the column [C ~> degC]. + Se, & ! Estimated final values of S in the column [S ~> ppt]. + dTe, & ! Running (1-way) estimates of temperature change [C ~> degC]. + dSe, & ! Running (1-way) estimates of salinity change [S ~> ppt]. Th_a, & ! An effective temperature times a thickness in the layer above, including implicit - ! mixing effects with other yet higher layers [degC H ~> degC m or degC kg m-2]. + ! mixing effects with other yet higher layers [C H ~> degC m or degC kg m-2]. Sh_a, & ! An effective salinity times a thickness in the layer above, including implicit - ! mixing effects with other yet higher layers [ppt H ~> ppt m or ppt kg m-2]. + ! mixing effects with other yet higher layers [S H ~> ppt m or ppt kg m-2]. Th_b, & ! An effective temperature times a thickness in the layer below, including implicit - ! mixing effects with other yet lower layers [degC H ~> degC m or degC kg m-2]. + ! mixing effects with other yet lower layers [C H ~> degC m or degC kg m-2]. Sh_b ! An effective salinity times a thickness in the layer below, including implicit - ! mixing effects with other yet lower layers [ppt H ~> ppt m or ppt kg m-2]. + ! mixing effects with other yet lower layers [S H ~> ppt m or ppt kg m-2]. real, dimension(SZK_(GV)+1) :: & MixLen_shape, & ! A nondimensional shape factor for the mixing length that ! gives it an appropriate asymptotic value at the bottom of @@ -659,15 +659,15 @@ subroutine ePBL_column(h, u, v, T0, S0, dSV_dT, dSV_dS, TKE_forcing, B_flux, abs real :: tot_TKE ! The total TKE available to support mixing at interface K [R Z3 T-2 ~> J m-2]. real :: TKE_here ! The total TKE at this point in the algorithm [R Z3 T-2 ~> J m-2]. real :: dT_km1_t2 ! A diffusivity-independent term related to the temperature - ! change in the layer above the interface [degC]. + ! change in the layer above the interface [C ~> degC]. real :: dS_km1_t2 ! A diffusivity-independent term related to the salinity - ! change in the layer above the interface [ppt]. + ! change in the layer above the interface [S ~> ppt]. real :: dTe_term ! A diffusivity-independent term related to the temperature - ! change in the layer below the interface [degC H ~> degC m or degC kg m-2]. + ! change in the layer below the interface [C H ~> degC m or degC kg m-2]. real :: dSe_term ! A diffusivity-independent term related to the salinity - ! change in the layer above the interface [ppt H ~> ppt m or ppt kg m-2]. - real :: dTe_t2 ! A part of dTe_term [degC H ~> degC m or degC kg m-2]. - real :: dSe_t2 ! A part of dSe_term [ppt H ~> ppt m or ppt kg m-2]. + ! change in the layer above the interface [S H ~> ppt m or ppt kg m-2]. + real :: dTe_t2 ! A part of dTe_term [C H ~> degC m or degC kg m-2]. + real :: dSe_t2 ! A part of dSe_term [S H ~> ppt m or ppt kg m-2]. real :: dPE_conv ! The convective change in column potential energy [R Z3 T-2 ~> J m-2]. real :: MKE_src ! The mean kinetic energy source of TKE due to Kddt_h(K) [R Z3 T-2 ~> J m-2]. real :: dMKE_src_dK ! The partial derivative of MKE_src with Kddt_h(K) [R Z3 T-2 H-1 ~> J m-3 or J kg-1]. @@ -733,8 +733,8 @@ subroutine ePBL_column(h, u, v, T0, S0, dSV_dT, dSV_dS, TKE_forcing, B_flux, abs real :: dPE_debug, mixing_debug real, dimension(20) :: TKE_left_itt, PE_chg_itt, Kddt_h_itt, dPEa_dKd_itt, MKE_src_itt real, dimension(SZK_(GV)) :: mech_TKE_k, conv_PErel_k, nstar_k - real, dimension(SZK_(GV)) :: dT_expect !< Expected temperature changes [degC] - real, dimension(SZK_(GV)) :: dS_expect !< Expected salinity changes [ppt] + real, dimension(SZK_(GV)) :: dT_expect !< Expected temperature changes [C ~> degC] + real, dimension(SZK_(GV)) :: dS_expect !< Expected salinity changes [S ~> ppt] integer, dimension(SZK_(GV)) :: num_itts integer :: k, nz, itt, max_itt @@ -1448,51 +1448,51 @@ subroutine find_PE_chg(Kddt_h0, dKddt_h, hp_a, hp_b, Th_a, Sh_a, Th_b, Sh_b, & !! Kddt_h for the interface above [H ~> m or kg m-2]. real, intent(in) :: Th_a !< An effective temperature times a thickness in the layer !! above, including implicit mixing effects with other - !! yet higher layers [degC H ~> degC m or degC kg m-2]. + !! yet higher layers [C H ~> degC m or degC kg m-2]. real, intent(in) :: Sh_a !< An effective salinity times a thickness in the layer !! above, including implicit mixing effects with other - !! yet higher layers [degC H ~> degC m or degC kg m-2]. + !! yet higher layers [S H ~> ppt m or ppt kg m-2]. real, intent(in) :: Th_b !< An effective temperature times a thickness in the layer !! below, including implicit mixing effects with other - !! yet lower layers [degC H ~> degC m or degC kg m-2]. + !! yet lower layers [C H ~> degC m or degC kg m-2]. real, intent(in) :: Sh_b !< An effective salinity times a thickness in the layer !! below, including implicit mixing effects with other - !! yet lower layers [degC H ~> degC m or degC kg m-2]. + !! yet lower layers [S H ~> ppt m or ppt kg m-2]. real, intent(in) :: dT_to_dPE_a !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating !! a layer's temperature change to the change in column potential !! energy, including all implicit diffusive changes in the - !! temperatures of all the layers above [R Z3 T-2 degC-1 ~> J m-2 degC-1]. + !! temperatures of all the layers above [R Z3 T-2 C-1 ~> J m-2 degC-1]. real, intent(in) :: dS_to_dPE_a !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating !! a layer's salinity change to the change in column potential !! energy, including all implicit diffusive changes in the - !! salinities of all the layers above [R Z3 T-2 ppt-1 ~> J m-2 ppt-1]. + !! salinities of all the layers above [R Z3 T-2 S-1 ~> J m-2 ppt-1]. real, intent(in) :: dT_to_dPE_b !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating !! a layer's temperature change to the change in column potential !! energy, including all implicit diffusive changes in the - !! temperatures of all the layers below [R Z3 T-2 degC-1 ~> J m-2 degC-1]. + !! temperatures of all the layers below [R Z3 T-2 C-1 ~> J m-2 degC-1]. real, intent(in) :: dS_to_dPE_b !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating !! a layer's salinity change to the change in column potential !! energy, including all implicit diffusive changes in the - !! salinities of all the layers below [R Z3 T-2 ppt-1 ~> J m-2 ppt-1]. + !! salinities of all the layers below [R Z3 T-2 S-1 ~> J m-2 ppt-1]. real, intent(in) :: pres_Z !< The rescaled hydrostatic interface pressure, which relates !! the changes in column thickness to the energy that is radiated !! as gravity waves and unavailable to drive mixing [R Z2 T-2 ~> J m-3]. real, intent(in) :: dT_to_dColHt_a !< A factor (mass_lay*dSColHtc_vol/dT) relating !! a layer's temperature change to the change in column !! height, including all implicit diffusive changes - !! in the temperatures of all the layers above [Z degC-1 ~> m degC-1]. + !! in the temperatures of all the layers above [Z C-1 ~> m degC-1]. real, intent(in) :: dS_to_dColHt_a !< A factor (mass_lay*dSColHtc_vol/dS) relating !! a layer's salinity change to the change in column !! height, including all implicit diffusive changes - !! in the salinities of all the layers above [Z ppt-1 ~> m ppt-1]. + !! in the salinities of all the layers above [Z S-1 ~> m ppt-1]. real, intent(in) :: dT_to_dColHt_b !< A factor (mass_lay*dSColHtc_vol/dT) relating !! a layer's temperature change to the change in column !! height, including all implicit diffusive changes - !! in the temperatures of all the layers below [Z degC-1 ~> m degC-1]. + !! in the temperatures of all the layers below [Z C-1 ~> m degC-1]. real, intent(in) :: dS_to_dColHt_b !< A factor (mass_lay*dSColHtc_vol/dS) relating !! a layer's salinity change to the change in column !! height, including all implicit diffusive changes - !! in the salinities of all the layers below [Z ppt-1 ~> m ppt-1]. + !! in the salinities of all the layers below [Z S-1 ~> m ppt-1]. real, intent(out) :: PE_chg !< The change in column potential energy from applying !! Kddt_h at the present interface [R Z3 T-2 ~> J m-2]. @@ -1509,8 +1509,8 @@ subroutine find_PE_chg(Kddt_h0, dKddt_h, hp_a, hp_b, Th_a, Sh_a, Th_b, Sh_b, & ! Local variables real :: hps ! The sum of the two effective pivot thicknesses [H ~> m or kg m-2]. real :: bdt1 ! A product of the two pivot thicknesses plus a diffusive term [H2 ~> m2 or kg2 m-4]. - real :: dT_c ! The core term in the expressions for the temperature changes [degC H2 ~> degC m2 or degC kg2 m-4]. - real :: dS_c ! The core term in the expressions for the salinity changes [ppt H2 ~> ppt m2 or ppt kg2 m-4]. + real :: dT_c ! The core term in the expressions for the temperature changes [C H2 ~> degC m2 or degC kg2 m-4]. + real :: dS_c ! The core term in the expressions for the salinity changes [S H2 ~> ppt m2 or ppt kg2 m-4]. real :: PEc_core ! The diffusivity-independent core term in the expressions ! for the potential energy changes [R Z2 T-2 ~> J m-3]. real :: ColHt_core ! The diffusivity-independent core term in the expressions @@ -1588,48 +1588,48 @@ subroutine find_PE_chg_orig(Kddt_h, h_k, b_den_1, dTe_term, dSe_term, & !! is a fraction (determined from the tridiagonal solver) of !! Kddt_h for the interface above [H ~> m or kg m-2]. real, intent(in) :: dTe_term !< A diffusivity-independent term related to the temperature change - !! in the layer below the interface [degC H ~> degC m or degC kg m-2]. + !! in the layer below the interface [C H ~> degC m or degC kg m-2]. real, intent(in) :: dSe_term !< A diffusivity-independent term related to the salinity change - !! in the layer below the interface [ppt H ~> ppt m or ppt kg m-2]. + !! in the layer below the interface [S H ~> ppt m or ppt kg m-2]. real, intent(in) :: dT_km1_t2 !< A diffusivity-independent term related to the - !! temperature change in the layer above the interface [degC]. + !! temperature change in the layer above the interface [C ~> degC]. real, intent(in) :: dS_km1_t2 !< A diffusivity-independent term related to the - !! salinity change in the layer above the interface [ppt]. + !! salinity change in the layer above the interface [S ~> ppt]. real, intent(in) :: pres_Z !< The rescaled hydrostatic interface pressure, which relates !! the changes in column thickness to the energy that is radiated !! as gravity waves and unavailable to drive mixing [R Z2 T-2 ~> J m-3]. real, intent(in) :: dT_to_dPE_k !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating !! a layer's temperature change to the change in column potential !! energy, including all implicit diffusive changes in the - !! temperatures of all the layers below [R Z3 T-2 degC-1 ~> J m-2 degC-1]. + !! temperatures of all the layers below [R Z3 T-2 C-1 ~> J m-2 degC-1]. real, intent(in) :: dS_to_dPE_k !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating !! a layer's salinity change to the change in column potential !! energy, including all implicit diffusive changes in the - !! in the salinities of all the layers below [R Z3 T-2 ppt-1 ~> J m-2 ppt-1]. + !! in the salinities of all the layers below [R Z3 T-2 S-1 ~> J m-2 ppt-1]. real, intent(in) :: dT_to_dPEa !< A factor (pres_lay*mass_lay*dSpec_vol/dT) relating !! a layer's temperature change to the change in column potential !! energy, including all implicit diffusive changes in the - !! temperatures of all the layers above [R Z3 T-2 degC-1 ~> J m-2 degC-1]. + !! temperatures of all the layers above [R Z3 T-2 C-1 ~> J m-2 degC-1]. real, intent(in) :: dS_to_dPEa !< A factor (pres_lay*mass_lay*dSpec_vol/dS) relating !! a layer's salinity change to the change in column potential !! energy, including all implicit diffusive changes in the - !! salinities of all the layers above [R Z3 T-2 ppt-1 ~> J m-2 ppt-1]. + !! salinities of all the layers above [R Z3 T-2 S-1 ~> J m-2 ppt-1]. real, intent(in) :: dT_to_dColHt_k !< A factor (mass_lay*dSColHtc_vol/dT) relating !! a layer's temperature change to the change in column !! height, including all implicit diffusive changes in the - !! temperatures of all the layers below [Z degC-1 ~> m degC-1]. + !! temperatures of all the layers below [Z C-1 ~> m degC-1]. real, intent(in) :: dS_to_dColHt_k !< A factor (mass_lay*dSColHtc_vol/dS) relating !! a layer's salinity change to the change in column !! height, including all implicit diffusive changes - !! in the salinities of all the layers below [Z ppt-1 ~> m ppt-1]. + !! in the salinities of all the layers below [Z S-1 ~> m ppt-1]. real, intent(in) :: dT_to_dColHta !< A factor (mass_lay*dSColHtc_vol/dT) relating !! a layer's temperature change to the change in column !! height, including all implicit diffusive changes - !! in the temperatures of all the layers above [Z degC-1 ~> m degC-1]. + !! in the temperatures of all the layers above [Z C-1 ~> m degC-1]. real, intent(in) :: dS_to_dColHta !< A factor (mass_lay*dSColHtc_vol/dS) relating !! a layer's salinity change to the change in column !! height, including all implicit diffusive changes - !! in the salinities of all the layers above [Z ppt-1 ~> m ppt-1]. + !! in the salinities of all the layers above [Z S-1 ~> m ppt-1]. real, intent(out) :: PE_chg !< The change in column potential energy from applying !! Kddt_h at the present interface [R Z3 T-2 ~> J m-2]. @@ -1656,14 +1656,14 @@ subroutine find_PE_chg_orig(Kddt_h, h_k, b_den_1, dTe_term, dSe_term, & real :: ColHt_chg ! The change in column thickness [Z ~> m]. real :: dColHt_max ! The change in column thickness for infinite diffusivity [Z ~> m]. real :: dColHt_dKd ! The partial derivative of column thickness with Kddt_h [Z H-1 ~> nondim or m3 kg-1] - real :: dT_k, dT_km1 ! Temperature changes in layers k and k-1 [degC] - real :: dS_k, dS_km1 ! Salinity changes in layers k and k-1 [ppt] + real :: dT_k, dT_km1 ! Temperature changes in layers k and k-1 [C ~> degC] + real :: dS_k, dS_km1 ! Salinity changes in layers k and k-1 [S ~> ppt] real :: I_Kr_denom ! Temporary array [H-2 ~> m-2 or m4 kg-2] real :: dKr_dKd ! Temporary array [H-2 ~> m-2 or m4 kg-2] real :: ddT_k_dKd, ddT_km1_dKd ! Temporary arrays indicating the temperature changes - ! per unit change in Kddt_h [degC H-1 ~> degC m-1 or degC m2 kg-1] + ! per unit change in Kddt_h [C H-1 ~> degC m-1 or degC m2 kg-1] real :: ddS_k_dKd, ddS_km1_dKd ! Temporary arrays indicating the salinity changes - ! per unit change in Kddt_h [ppt H-1 ~> ppt m-1 or ppt m2 kg-1] + ! per unit change in Kddt_h [S H-1 ~> ppt m-1 or ppt m2 kg-1] b1 = 1.0 / (b_den_1 + Kddt_h) b1Kd = Kddt_h*b1 diff --git a/src/parameterizations/vertical/MOM_entrain_diffusive.F90 b/src/parameterizations/vertical/MOM_entrain_diffusive.F90 index 45d442f98c..beb207624a 100644 --- a/src/parameterizations/vertical/MOM_entrain_diffusive.F90 +++ b/src/parameterizations/vertical/MOM_entrain_diffusive.F90 @@ -175,9 +175,9 @@ subroutine entrainment_diffusive(h, tv, fluxes, dt, G, GV, US, CS, ea, eb, & real, dimension(SZI_(G)) :: & pressure, & ! The pressure at an interface [R L2 T-2 ~> Pa]. T_eos, S_eos, & ! The potential temperature and salinity at which to - ! evaluate dRho_dT and dRho_dS [degC] and [ppt]. + ! evaluate dRho_dT and dRho_dS [C ~> degC] and [S ~> ppt]. dRho_dT, dRho_dS ! The partial derivatives of potential density with temperature and - ! salinity, [R degC-1 ~> kg m-3 degC-1] and [R ppt-1 ~> kg m-3 ppt-1]. + ! salinity, [R C-1 ~> kg m-3 degC-1] and [R S-1 ~> kg m-3 ppt-1]. real :: tolerance ! The tolerance within which E must be converged [H ~> m or kg m-2]. real :: Angstrom ! The minimum layer thickness [H ~> m or kg m-2]. @@ -848,7 +848,7 @@ subroutine entrainment_diffusive(h, tv, fluxes, dt, G, GV, US, CS, ea, eb, & S_eos(i) = 0.5*(tv%S(i,j,k-1) + tv%S(i,j,k)) endif enddo - call calculate_density_derivs(T_eos, S_eos, pressure, dRho_dT, dRho_dS, & + call calculate_density_derivs(T_EOS, S_EOS, pressure, dRho_dT, dRho_dS, & tv%eqn_of_state, EOSdom) do i=is,ie if ((k>kmb) .and. (k m or kg m-2] type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various !! thermodynamic variables real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(out) :: T_adj !< Adjusted potential temperature [degC]. + intent(out) :: T_adj !< Adjusted potential temperature [C ~> degC]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(out) :: S_adj !< Adjusted salinity [ppt]. + intent(out) :: S_adj !< Adjusted salinity [S ~> ppt]. real, dimension(:,:), pointer :: p_surf !< The pressure at the ocean surface [R L2 T-2 ~> Pa] (or NULL). real, intent(in) :: Kddt_smooth !< A smoothing vertical !! diffusivity times a timestep [H2 ~> m2 or kg2 m-4]. @@ -37,27 +37,27 @@ subroutine full_convection(G, GV, US, h, tv, T_adj, S_adj, p_surf, Kddt_smooth, ! Local variables real, dimension(SZI_(G),SZK_(GV)+1) :: & - dRho_dT, & ! The derivative of density with temperature [R degC-1 ~> kg m-3 degC-1] - dRho_dS ! The derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1]. + dRho_dT, & ! The derivative of density with temperature [R C-1 ~> kg m-3 degC-1] + dRho_dS ! The derivative of density with salinity [R S-1 ~> kg m-3 ppt-1]. real :: h_neglect, h0 ! A thickness that is so small it is usually lost ! in roundoff and can be neglected [H ~> m or kg m-2]. ! logical :: use_EOS ! If true, density is calculated from T & S using an equation of state. real, dimension(SZI_(G),SZK0_(G)) :: & Te_a, & ! A partially updated temperature estimate including the influence from - ! mixing with layers above rescaled by a factor of d_a [degC]. + ! mixing with layers above rescaled by a factor of d_a [C ~> degC]. ! This array is discretized on tracer cells, but contains an extra ! layer at the top for algorithmic convenience. Se_a ! A partially updated salinity estimate including the influence from - ! mixing with layers above rescaled by a factor of d_a [ppt]. + ! mixing with layers above rescaled by a factor of d_a [S ~> ppt]. ! This array is discretized on tracer cells, but contains an extra ! layer at the top for algorithmic convenience. real, dimension(SZI_(G),SZK_(GV)+1) :: & Te_b, & ! A partially updated temperature estimate including the influence from - ! mixing with layers below rescaled by a factor of d_b [degC]. + ! mixing with layers below rescaled by a factor of d_b [C ~> degC]. ! This array is discretized on tracer cells, but contains an extra ! layer at the bottom for algorithmic convenience. Se_b ! A partially updated salinity estimate including the influence from - ! mixing with layers below rescaled by a factor of d_b [ppt]. + ! mixing with layers below rescaled by a factor of d_b [S ~> ppt]. ! This array is discretized on tracer cells, but contains an extra ! layer at the bottom for algorithmic convenience. real, dimension(SZI_(G),SZK_(GV)+1) :: & @@ -270,22 +270,22 @@ end subroutine full_convection !! above and below, including partial calculations from a tridiagonal solver. function is_unstable(dRho_dT, dRho_dS, h_a, h_b, mix_A, mix_B, T_a, T_b, S_a, S_b, & Te_aa, Te_bb, Se_aa, Se_bb, d_A, d_B) - real, intent(in) :: dRho_dT !< The derivative of in situ density with temperature [R degC-1 ~> kg m-3 degC-1] - real, intent(in) :: dRho_dS !< The derivative of in situ density with salinity [R ppt-1 ~> kg m-3 ppt-1] + real, intent(in) :: dRho_dT !< The derivative of in situ density with temperature [R C-1 ~> kg m-3 degC-1] + real, intent(in) :: dRho_dS !< The derivative of in situ density with salinity [R S-1 ~> kg m-3 ppt-1] real, intent(in) :: h_a !< The thickness of the layer above [H ~> m or kg m-2] real, intent(in) :: h_b !< The thickness of the layer below [H ~> m or kg m-2] real, intent(in) :: mix_A !< The time integrated mixing rate of the interface above [H ~> m or kg m-2] real, intent(in) :: mix_B !< The time integrated mixing rate of the interface below [H ~> m or kg m-2] - real, intent(in) :: T_a !< The initial temperature of the layer above [degC] - real, intent(in) :: T_b !< The initial temperature of the layer below [degC] - real, intent(in) :: S_a !< The initial salinity of the layer below [ppt] - real, intent(in) :: S_b !< The initial salinity of the layer below [ppt] - real, intent(in) :: Te_aa !< The estimated temperature two layers above rescaled by d_A [degC] - real, intent(in) :: Te_bb !< The estimated temperature two layers below rescaled by d_B [degC] - real, intent(in) :: Se_aa !< The estimated salinity two layers above rescaled by d_A [ppt] - real, intent(in) :: Se_bb !< The estimated salinity two layers below rescaled by d_B [ppt] - real, intent(in) :: d_A !< The rescaling dependency across the interface above, nondim. - real, intent(in) :: d_B !< The rescaling dependency across the interface below, nondim. + real, intent(in) :: T_a !< The initial temperature of the layer above [C ~> degC] + real, intent(in) :: T_b !< The initial temperature of the layer below [C ~> degC] + real, intent(in) :: S_a !< The initial salinity of the layer below [S ~> ppt] + real, intent(in) :: S_b !< The initial salinity of the layer below [S ~> ppt] + real, intent(in) :: Te_aa !< The estimated temperature two layers above rescaled by d_A [C ~> degC] + real, intent(in) :: Te_bb !< The estimated temperature two layers below rescaled by d_B [C ~> degC] + real, intent(in) :: Se_aa !< The estimated salinity two layers above rescaled by d_A [S ~> ppt] + real, intent(in) :: Se_bb !< The estimated salinity two layers below rescaled by d_B [S ~> ppt] + real, intent(in) :: d_A !< The rescaling dependency across the interface above [nondim] + real, intent(in) :: d_B !< The rescaling dependency across the interface below [nondim] logical :: is_unstable !< The return value, true if the profile is statically unstable !! around the interface in question. @@ -316,10 +316,10 @@ subroutine smoothed_dRdT_dRdS(h, tv, Kddt, dR_dT, dR_dS, G, GV, US, j, p_surf, h real, intent(in) :: Kddt !< A diffusivity times a time increment [H2 ~> m2 or kg2 m-4]. real, dimension(SZI_(G),SZK_(GV)+1), & intent(out) :: dR_dT !< Derivative of locally referenced - !! potential density with temperature [R degC-1 ~> kg m-3 degC-1] + !! potential density with temperature [R C-1 ~> kg m-3 degC-1] real, dimension(SZI_(G),SZK_(GV)+1), & intent(out) :: dR_dS !< Derivative of locally referenced - !! potential density with salinity [R ppt-1 ~> kg m-3 ppt-1] + !! potential density with salinity [R S-1 ~> kg m-3 ppt-1] type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type integer, intent(in) :: j !< The j-point to work on. real, dimension(:,:), pointer :: p_surf !< The pressure at the ocean surface [R L2 T-2 ~> Pa]. @@ -331,11 +331,11 @@ subroutine smoothed_dRdT_dRdS(h, tv, Kddt, dR_dT, dR_dS, G, GV, US, j, p_surf, h real :: b1(SZI_(G)) ! A tridiagonal solver variable [H-1 ~> m-1 or m2 kg-1] real :: d1(SZI_(G)) ! A tridiagonal solver variable [nondim] real :: c1(SZI_(G),SZK_(GV)) ! A tridiagonal solver variable [nondim] - real :: T_f(SZI_(G),SZK_(GV)) ! Filtered temperatures [degC] - real :: S_f(SZI_(G),SZK_(GV)) ! Filtered salinities [ppt] + real :: T_f(SZI_(G),SZK_(GV)) ! Filtered temperatures [C ~> degC] + real :: S_f(SZI_(G),SZK_(GV)) ! Filtered salinities [S ~> ppt] real :: pres(SZI_(G)) ! Interface pressures [R L2 T-2 ~> Pa]. - real :: T_EOS(SZI_(G)) ! Filtered and vertically averaged temperatures [degC] - real :: S_EOS(SZI_(G)) ! Filtered and vertically averaged salinities [ppt] + real :: T_EOS(SZI_(G)) ! Filtered and vertically averaged temperatures [C ~> degC] + real :: S_EOS(SZI_(G)) ! Filtered and vertically averaged salinities [S ~> ppt] real :: kap_dt_x2 ! The product of 2*kappa*dt [H2 ~> m2 or kg2 m-4]. real :: h_neglect, h0 ! Negligible thicknesses to allow for zero thicknesses, ! [H ~> m or kg m-2]. diff --git a/src/parameterizations/vertical/MOM_geothermal.F90 b/src/parameterizations/vertical/MOM_geothermal.F90 index 3fca484349..ce19609210 100644 --- a/src/parameterizations/vertical/MOM_geothermal.F90 +++ b/src/parameterizations/vertical/MOM_geothermal.F90 @@ -26,7 +26,7 @@ module MOM_geothermal logical :: initialized = .false. !< True if this control structure has been initialized. real :: dRcv_dT_inplace !< The value of dRcv_dT above which (dRcv_dT is negative) the !! water is heated in place instead of moving upward between - !! layers in non-ALE layered mode [R degC-1 ~> kg m-3 degC-1] + !! layers in non-ALE layered mode [R C-1 ~> kg m-3 degC-1] real, allocatable, dimension(:,:) :: geo_heat !< The geothermal heat flux [Q R Z T-1 ~> W m-2] real :: geothermal_thick !< The thickness over which geothermal heating is !! applied [H ~> m or kg m-2] @@ -72,40 +72,40 @@ subroutine geothermal_entraining(h, tv, dt, ea, eb, G, GV, US, CS, halo) integer, optional, intent(in) :: halo !< Halo width over which to work ! Local variables real, dimension(SZI_(G)) :: & - heat_rem, & ! remaining heat [H degC ~> m degC or kg degC m-2] + heat_rem, & ! remaining heat [H C ~> m degC or kg degC m-2] h_geo_rem, & ! remaining thickness to apply geothermal heating [H ~> m or kg m-2] Rcv_BL, & ! coordinate density in the deepest variable density layer [R ~> kg m-3] p_ref ! coordinate densities reference pressure [R L2 T-2 ~> Pa] real, dimension(2) :: & - T2, S2, & ! temp and saln in the present and target layers [degC] and [ppt] - dRcv_dT_, & ! partial derivative of coordinate density wrt temp [R degC-1 ~> kg m-3 degC-1] - dRcv_dS_ ! partial derivative of coordinate density wrt saln [R ppt-1 ~> kg m-3 ppt-1] + T2, S2, & ! temp and saln in the present and target layers [C ~> degC] and [S ~> ppt] + dRcv_dT_, & ! partial derivative of coordinate density wrt temp [R C-1 ~> kg m-3 degC-1] + dRcv_dS_ ! partial derivative of coordinate density wrt saln [R S-1 ~> kg m-3 ppt-1] real :: Angstrom, H_neglect ! small thicknesses [H ~> m or kg m-2] real :: Rcv ! coordinate density of present layer [R ~> kg m-3] real :: Rcv_tgt ! coordinate density of target layer [R ~> kg m-3] real :: dRcv ! difference between Rcv and Rcv_tgt [R ~> kg m-3] real :: dRcv_dT ! partial derivative of coordinate density wrt temp - ! in the present layer [R degC-1 ~> kg m-3 degC-1]; usually negative + ! in the present layer [R C-1 ~> kg m-3 degC-1]; usually negative real :: h_heated ! thickness that is being heated [H ~> m or kg m-2] - real :: heat_avail ! heating available for the present layer [degC H ~> degC m or degC kg m-2] + real :: heat_avail ! heating available for the present layer [C H ~> degC m or degC kg m-2] real :: heat_in_place ! heating to warm present layer w/o movement between layers - ! [degC H ~> degC m or degC kg m-2] + ! [C H ~> degC m or degC kg m-2] real :: heat_trans ! heating available to move water from present layer to target - ! layer [degC H ~> degC m or degC kg m-2] + ! layer [C H ~> degC m or degC kg m-2] real :: heating ! heating used to move water from present layer to target layer - ! [degC H ~> degC m or degC kg m-2] + ! [C H ~> degC m or degC kg m-2] ! 0 <= heating <= heat_trans real :: h_transfer ! thickness moved between layers [H ~> m or kg m-2] real :: wt_in_place ! relative weighting that goes from 0 to 1 [nondim] real :: I_h ! inverse thickness [H-1 ~> m-1 or m2 kg-1] - real :: dTemp ! temperature increase in a layer [degC] + real :: dTemp ! temperature increase in a layer [C ~> degC] real :: Irho_cp ! inverse of heat capacity per unit layer volume - ! [degC H Q-1 R-1 Z-1 ~> degC m3 J-1 or degC kg J-1] + ! [C H Q-1 R-1 Z-1 ~> degC m3 J-1 or degC kg J-1] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: & - T_old, & ! Temperature of each layer before any heat is added, for diagnostics [degC] + T_old, & ! Temperature of each layer before any heat is added, for diagnostics [C ~> degC] h_old, & ! Thickness of each layer before any heat is added, for diagnostics [H ~> m or kg m-2] work_3d ! Scratch variable used to calculate changes due to geothermal real :: Idt ! inverse of the timestep [T-1 ~> s-1] @@ -373,17 +373,17 @@ subroutine geothermal_in_place(h, tv, dt, G, GV, US, CS, halo) ! Local variables real, dimension(SZI_(G)) :: & - heat_rem, & ! remaining heat [H degC ~> m degC or kg degC m-2] + heat_rem, & ! remaining heat [H C ~> m degC or kg degC m-2] h_geo_rem ! remaining thickness to apply geothermal heating [H ~> m or kg m-2] real :: Angstrom, H_neglect ! small thicknesses [H ~> m or kg m-2] - real :: heat_here ! heating applied to the present layer [degC H ~> degC m or degC kg m-2] - real :: dTemp ! temperature increase in a layer [degC] + real :: heat_here ! heating applied to the present layer [C H ~> degC m or degC kg m-2] + real :: dTemp ! temperature increase in a layer [C ~> degC] real :: Irho_cp ! inverse of heat capacity per unit layer volume - ! [degC H Q-1 R-1 Z-1 ~> degC m3 J-1 or degC kg J-1] + ! [C H Q-1 R-1 Z-1 ~> degC m3 J-1 or degC kg J-1] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: & - dTdt_diag ! Diagnostic of temperature tendency [degC T-1 ~> degC s-1] which might be + dTdt_diag ! Diagnostic of temperature tendency [C T-1 ~> degC s-1] which might be ! converted into a layer-integrated heat tendency [Q R Z T-1 ~> W m-2] real :: Idt ! inverse of the timestep [T-1 ~> s-1] logical :: do_any ! True if there is more to be done on the current j-row. @@ -475,7 +475,7 @@ subroutine geothermal_in_place(h, tv, dt, G, GV, US, CS, halo) if (CS%id_internal_heat_heat_tendency > 0) then do k=1,nz ; do j=js,je ; do i=is,ie ! Dangerously reuse dTdt_diag for a related variable with different units, going from - ! units of [degC T-1 ~> degC s-1] to units of [Q R Z T-1 ~> W m-2] + ! units of [C T-1 ~> degC s-1] to units of [Q R Z T-1 ~> W m-2] dTdt_diag(i,j,k) = (GV%H_to_RZ*tv%C_p) * (h(i,j,k) * dTdt_diag(i,j,k)) enddo ; enddo ; enddo call post_data(CS%id_internal_heat_heat_tendency, dTdt_diag, CS%diag, alt_h=h) @@ -537,7 +537,7 @@ subroutine geothermal_init(Time, G, GV, US, param_file, diag, CS, useALEalgorith "The value of drho_dT above which geothermal heating "//& "simply heats water in place instead of moving it between "//& "isopycnal layers. This must be negative.", & - units="kg m-3 K-1", scale=US%kg_m3_to_R, default=-0.01, & + units="kg m-3 K-1", scale=US%kg_m3_to_R*US%C_to_degC, default=-0.01, & do_not_log=((GV%nk_rho_varies<=0).or.(GV%nk_rho_varies>=GV%ke)) ) if (CS%dRcv_dT_inplace >= 0.0) call MOM_error(FATAL, "geothermal_init: "//& "GEOTHERMAL_DRHO_DT_INPLACE must be negative.") @@ -580,7 +580,7 @@ subroutine geothermal_init(Time, G, GV, US, param_file, diag, CS, useALEalgorith CS%id_internal_heat_temp_tendency=register_diag_field('ocean_model', & 'internal_heat_temp_tendency', diag%axesTL, Time, & 'Temperature tendency (in 3D) due to internal (geothermal) sources', & - 'degC s-1', conversion=US%s_to_T, v_extensive=.true.) + 'degC s-1', conversion=US%C_to_degC*US%s_to_T, v_extensive=.true.) if (.not.useALEalgorithm) then ! Do not offer this diagnostic if heating will be in place. CS%id_internal_heat_h_tendency=register_diag_field('ocean_model', & diff --git a/src/parameterizations/vertical/MOM_internal_tide_input.F90 b/src/parameterizations/vertical/MOM_internal_tide_input.F90 index f68e518a14..ff2180497b 100644 --- a/src/parameterizations/vertical/MOM_internal_tide_input.F90 +++ b/src/parameterizations/vertical/MOM_internal_tide_input.F90 @@ -96,7 +96,7 @@ subroutine set_int_tide_input(u, v, h, tv, fluxes, itide, dt, G, GV, US, CS) N2_bot ! The bottom squared buoyancy frequency [T-2 ~> s-2]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: & - T_f, S_f ! The temperature and salinity in [degC] and [ppt] with the values in + T_f, S_f ! The temperature and salinity in [C ~> degC] and [S ~> ppt] with the values in ! the massless layers filled vertically by diffusion. logical :: use_EOS ! If true, density is calculated from T & S using an ! equation of state. @@ -180,9 +180,9 @@ subroutine find_N2_bottom(h, tv, T_f, S_f, h2, fluxes, G, GV, US, N2_bot) type(thermo_var_ptrs), intent(in) :: tv !< A structure containing pointers to the !! thermodynamic fields real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: T_f !< Temperature after vertical filtering to - !! smooth out the values in thin layers [degC]. + !! smooth out the values in thin layers [C ~> degC]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: S_f !< Salinity after vertical filtering to - !! smooth out the values in thin layers [ppt]. + !! smooth out the values in thin layers [S ~> ppt]. real, dimension(SZI_(G),SZJ_(G)), intent(in) :: h2 !< Bottom topographic roughness [Z2 ~> m2]. type(forcing), intent(in) :: fluxes !< A structure of thermodynamic surface fluxes real, dimension(SZI_(G),SZJ_(G)), intent(out) :: N2_bot !< The squared buoyancy freqency at the @@ -192,14 +192,14 @@ subroutine find_N2_bottom(h, tv, T_f, S_f, h2, fluxes, G, GV, US, N2_bot) dRho_int ! The unfiltered density differences across interfaces [R ~> kg m-3]. real, dimension(SZI_(G)) :: & pres, & ! The pressure at each interface [R L2 T-2 ~> Pa]. - Temp_int, & ! The temperature at each interface [degC]. - Salin_int, & ! The salinity at each interface [ppt]. + Temp_int, & ! The temperature at each interface [C ~> degC] + Salin_int, & ! The salinity at each interface [S ~> ppt] drho_bot, & ! The density difference at the bottom of a layer [R ~> kg m-3] h_amp, & ! The amplitude of topographic roughness [Z ~> m]. hb, & ! The depth below a layer [Z ~> m]. z_from_bot, & ! The height of a layer center above the bottom [Z ~> m]. - dRho_dT, & ! The partial derivative of density with temperature [R degC-1 ~> kg m-3 degC-1] - dRho_dS ! The partial derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1]. + dRho_dT, & ! The partial derivative of density with temperature [R C-1 ~> kg m-3 degC-1] + dRho_dS ! The partial derivative of density with salinity [R S-1 ~> kg m-3 ppt-1]. real :: dz_int ! The thickness associated with an interface [Z ~> m]. real :: G_Rho0 ! The gravitation acceleration divided by the Boussinesq diff --git a/src/parameterizations/vertical/MOM_kappa_shear.F90 b/src/parameterizations/vertical/MOM_kappa_shear.F90 index f0f958d49d..a95edbad52 100644 --- a/src/parameterizations/vertical/MOM_kappa_shear.F90 +++ b/src/parameterizations/vertical/MOM_kappa_shear.F90 @@ -142,7 +142,7 @@ subroutine Calculate_kappa_shear(u_in, v_in, h, tv, p_surf, kappa_io, tke_io, & real, dimension(SZI_(G),SZK_(GV)) :: & h_2d, & ! A 2-D version of h, but converted to [Z ~> m]. u_2d, v_2d, & ! 2-D versions of u_in and v_in, converted to [L T-1 ~> m s-1]. - T_2d, S_2d, rho_2d ! 2-D versions of T [degC], S [ppt], and rho [R ~> kg m-3]. + T_2d, S_2d, rho_2d ! 2-D versions of T [C ~> degC], S [S ~> ppt], and rho [R ~> kg m-3]. real, dimension(SZI_(G),SZK_(GV)+1) :: & kappa_2d, & ! 2-D version of kappa_io [Z2 T-1 ~> m2 s-1]. tke_2d ! 2-D version tke_io [Z2 T-2 ~> m2 s-2]. @@ -151,8 +151,8 @@ subroutine Calculate_kappa_shear(u_in, v_in, h, tv, p_surf, kappa_io, tke_io, & dz, & ! The layer thickness [Z ~> m]. u0xdz, & ! The initial zonal velocity times dz [Z L T-1 ~> m2 s-1]. v0xdz, & ! The initial meridional velocity times dz [Z L T-1 ~> m2 s-1]. - T0xdz, & ! The initial temperature times dz [degC Z ~> degC m]. - S0xdz ! The initial salinity times dz [ppt Z ~> ppt m]. + T0xdz, & ! The initial temperature times dz [C Z ~> degC m]. + S0xdz ! The initial salinity times dz [S Z ~> ppt m]. real, dimension(SZK_(GV)+1) :: & kappa, & ! The shear-driven diapycnal diffusivity at an interface [Z2 T-1 ~> m2 s-1]. tke, & ! The Turbulent Kinetic Energy per unit mass at an interface [Z2 T-2 ~> m2 s-2]. @@ -339,9 +339,9 @@ subroutine Calc_kappa_shear_vertex(u_in, v_in, h, T_in, S_in, tv, p_surf, kappa_ 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)), & - intent(in) :: T_in !< Layer potential temperatures [degC] + intent(in) :: T_in !< Layer potential temperatures [C ~> degC] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(in) :: S_in !< Layer salinities in ppt. + intent(in) :: S_in !< Layer salinities [S ~> ppt] type(thermo_var_ptrs), intent(in) :: tv !< A structure containing pointers to any !! available thermodynamic fields. Absent fields !! have NULL ptrs. @@ -366,7 +366,7 @@ subroutine Calc_kappa_shear_vertex(u_in, v_in, h, T_in, S_in, tv, p_surf, kappa_ real, dimension(SZIB_(G),SZK_(GV)) :: & h_2d, & ! A 2-D version of h, but converted to [Z ~> m]. u_2d, v_2d, & ! 2-D versions of u_in and v_in, converted to [L T-1 ~> m s-1]. - T_2d, S_2d, rho_2d ! 2-D versions of T [degC], S [ppt], and rho [R ~> kg m-3]. + T_2d, S_2d, rho_2d ! 2-D versions of T [C ~> degC], S [S ~> ppt], and rho [R ~> kg m-3]. real, dimension(SZIB_(G),SZK_(GV)+1,2) :: & kappa_2d ! Quasi 2-D versions of kappa_io [Z2 T-1 ~> m2 s-1]. real, dimension(SZIB_(G),SZK_(GV)+1) :: & @@ -376,8 +376,8 @@ subroutine Calc_kappa_shear_vertex(u_in, v_in, h, T_in, S_in, tv, p_surf, kappa_ dz, & ! The layer thickness [Z ~> m]. u0xdz, & ! The initial zonal velocity times dz [L Z T-1 ~> m2 s-1]. v0xdz, & ! The initial meridional velocity times dz [L Z T-1 ~> m2 s-1]. - T0xdz, & ! The initial temperature times dz [degC Z ~> degC m]. - S0xdz ! The initial salinity times dz [ppt Z ~> ppt m]. + T0xdz, & ! The initial temperature times dz [C Z ~> degC m]. + S0xdz ! The initial salinity times dz [S Z ~> ppt m]. real, dimension(SZK_(GV)+1) :: & kappa, & ! The shear-driven diapycnal diffusivity at an interface [Z2 T-1 ~> m2 s-1]. tke, & ! The Turbulent Kinetic Energy per unit mass at an interface [Z2 T-2 ~> m2 s-2]. @@ -614,9 +614,9 @@ subroutine kappa_shear_column(kappa, tke, dt, nzc, f2, surface_pres, dz, & real, dimension(SZK_(GV)), & intent(in) :: v0xdz !< The initial meridional velocity times dz [Z L T-1 ~> m2 s-1]. real, dimension(SZK_(GV)), & - intent(in) :: T0xdz !< The initial temperature times dz [degC Z ~> degC m]. + intent(in) :: T0xdz !< The initial temperature times dz [C Z ~> degC m]. real, dimension(SZK_(GV)), & - intent(in) :: S0xdz !< The initial salinity times dz [ppt Z ~> ppt m]. + intent(in) :: S0xdz !< The initial salinity times dz [S Z ~> ppt m]. real, dimension(SZK_(GV)+1), & intent(out) :: kappa_avg !< The time-weighted average of kappa [Z2 T-1 ~> m2 s-1]. real, dimension(SZK_(GV)+1), & @@ -634,10 +634,10 @@ subroutine kappa_shear_column(kappa, tke, dt, nzc, f2, surface_pres, dz, & u, & ! The zonal velocity after a timestep of mixing [L T-1 ~> m s-1]. v, & ! The meridional velocity after a timestep of mixing [L T-1 ~> m s-1]. Idz, & ! The inverse of the distance between TKE points [Z-1 ~> m-1]. - T, & ! The potential temperature after a timestep of mixing [degC]. - Sal, & ! The salinity after a timestep of mixing [ppt]. + T, & ! The potential temperature after a timestep of mixing [C ~> degC]. + Sal, & ! The salinity after a timestep of mixing [S ~> ppt]. u_test, v_test, & ! Temporary velocities [L T-1 ~> m s-1]. - T_test, S_test ! Temporary temperatures [degC] and salinities [ppt]. + T_test, S_test ! Temporary temperatures [C ~> degC] and salinities [S ~> ppt]. real, dimension(nzc+1) :: & N2, & ! The squared buoyancy frequency at an interface [T-2 ~> s-2]. @@ -658,10 +658,10 @@ subroutine kappa_shear_column(kappa, tke, dt, nzc, f2, surface_pres, dz, & tke_pred, & ! The value of TKE from a predictor step [Z2 T-2 ~> m2 s-2]. kappa_pred, & ! The value of kappa from a predictor step [Z2 T-1 ~> m2 s-1]. pressure, & ! The pressure at an interface [R L2 T-2 ~> Pa]. - T_int, & ! The temperature interpolated to an interface [degC]. - Sal_int, & ! The salinity interpolated to an interface [ppt]. + T_int, & ! The temperature interpolated to an interface [C ~> degC]. + Sal_int, & ! The salinity interpolated to an interface [S ~> ppt]. dbuoy_dT, & ! The partial derivatives of buoyancy with changes in temperature - dbuoy_dS, & ! and salinity, [Z T-2 degC-1 ~> m s-2 degC-1] and [Z T-2 ppt-1 ~> m s-2 ppt-1]. + dbuoy_dS, & ! and salinity, [Z T-2 C-1 ~> m s-2 degC-1] and [Z T-2 S-1 ~> m s-2 ppt-1]. I_L2_bdry, & ! The inverse of the square of twice the harmonic mean ! distance to the top and bottom boundaries [Z-2 ~> m-2]. K_Q, & ! Diffusivity divided by TKE [T ~> s]. @@ -1035,22 +1035,22 @@ subroutine calculate_projected_state(kappa, u0, v0, T0, S0, dt, nz, dz, I_dz_int !! [Z2 T-1 ~> m2 s-1]. real, dimension(nz), intent(in) :: u0 !< The initial zonal velocity [L T-1 ~> m s-1]. real, dimension(nz), intent(in) :: v0 !< The initial meridional velocity [L T-1 ~> m s-1]. - real, dimension(nz), intent(in) :: T0 !< The initial temperature [degC]. - real, dimension(nz), intent(in) :: S0 !< The initial salinity [ppt]. + real, dimension(nz), intent(in) :: T0 !< The initial temperature [C ~> degC]. + real, dimension(nz), intent(in) :: S0 !< The initial salinity [S ~> ppt]. real, intent(in) :: dt !< The time step [T ~> s]. real, dimension(nz), intent(in) :: dz !< The grid spacing of layers [Z ~> m]. real, dimension(nz+1), intent(in) :: I_dz_int !< The inverse of the layer's thicknesses !! [Z-1 ~> m-1]. real, dimension(nz+1), intent(in) :: dbuoy_dT !< The partial derivative of buoyancy with - !! temperature [Z T-2 degC-1 ~> m s-2 degC-1]. + !! temperature [Z T-2 C-1 ~> m s-2 degC-1]. real, dimension(nz+1), intent(in) :: dbuoy_dS !< The partial derivative of buoyancy with - !! salinity [Z T-2 ppt-1 ~> m s-2 ppt-1]. + !! salinity [Z T-2 S-1 ~> m s-2 ppt-1]. real, intent(in) :: vel_under !< Any velocities that are smaller in magnitude !! than this value are set to 0 [L T-1 ~> m s-1]. real, dimension(nz), intent(inout) :: u !< The zonal velocity after dt [L T-1 ~> m s-1]. real, dimension(nz), intent(inout) :: v !< The meridional velocity after dt [L T-1 ~> m s-1]. - real, dimension(nz), intent(inout) :: T !< The temperature after dt [degC]. - real, dimension(nz), intent(inout) :: Sal !< The salinity after dt [ppt]. + real, dimension(nz), intent(inout) :: T !< The temperature after dt [C ~> degC]. + real, dimension(nz), intent(inout) :: Sal !< The salinity after dt [S ~> ppt]. real, dimension(nz+1), intent(inout) :: N2 !< The buoyancy frequency squared at interfaces [T-2 ~> s-2]. real, dimension(nz+1), intent(inout) :: S2 !< The squared shear at interfaces [T-2 ~> s-2]. type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure. diff --git a/src/parameterizations/vertical/MOM_opacity.F90 b/src/parameterizations/vertical/MOM_opacity.F90 index d6d2e10393..7f9f61a1dc 100644 --- a/src/parameterizations/vertical/MOM_opacity.F90 +++ b/src/parameterizations/vertical/MOM_opacity.F90 @@ -554,11 +554,11 @@ subroutine absorbRemainingSW(G, GV, US, h, opacity_band, nsw, optics, j, dt, H_l !! shortwave that should be absorbed by !! each layer. real, dimension(SZI_(G),SZK_(GV)), intent(inout) :: T !< Layer potential/conservative - !! temperatures [degC] + !! temperatures [C ~> degC] real, dimension(max(1,nsw),SZI_(G)), intent(inout) :: Pen_SW_bnd !< Penetrating shortwave heating in !! each band that hits the bottom and will !! will be redistributed through the water - !! column [degC H ~> degC m or degC kg m-2], + !! column [C H ~> degC m or degC kg m-2], !! size nsw x SZI_(G). real, dimension(SZI_(G),SZK_(GV)), optional, intent(in) :: eps !< Small thickness that must remain in !! each layer, and which will not be @@ -566,16 +566,16 @@ subroutine absorbRemainingSW(G, GV, US, h, opacity_band, nsw, optics, j, dt, H_l integer, dimension(SZI_(G),SZK_(GV)), optional, intent(in) :: ksort !< Density-sorted k-indices. real, dimension(SZI_(G)), optional, intent(in) :: htot !< Total mixed layer thickness [H ~> m or kg m-2]. real, dimension(SZI_(G)), optional, intent(inout) :: Ttot !< Depth integrated mixed layer - !! temperature [degC H ~> degC m or degC kg m-2] + !! temperature [C H ~> degC m or degC kg m-2] real, dimension(SZI_(G),SZK_(GV)), optional, intent(in) :: dSV_dT !< The partial derivative of specific volume - !! with temperature [R-1 degC-1 ~> m3 kg-1 degC-1] + !! with temperature [R-1 C-1 ~> m3 kg-1 degC-1] real, dimension(SZI_(G),SZK_(GV)), optional, intent(inout) :: TKE !< The TKE sink from mixing the heating !! throughout a layer [R Z3 T-2 ~> J m-2]. ! Local variables real, dimension(SZI_(G),SZK_(GV)) :: & T_chg_above ! A temperature change that will be applied to all the thick - ! layers above a given layer [degC]. This is only nonzero if + ! layers above a given layer [C ~> degC]. This is only nonzero if ! adjustAbsorptionProfile is true, in which case the net ! change in the temperature of a layer is the sum of the ! direct heating of that layer plus T_chg_above from all of @@ -585,10 +585,10 @@ subroutine absorbRemainingSW(G, GV, US, h, opacity_band, nsw, optics, j, dt, H_l h_heat, & ! The thickness of the water column that will be heated by ! any remaining shortwave radiation [H ~> m or kg m-2]. T_chg, & ! The temperature change of thick layers due to the remaining - ! shortwave radiation and contributions from T_chg_above [degC]. + ! shortwave radiation and contributions from T_chg_above [C ~> degC]. Pen_SW_rem ! The sum across all wavelength bands of the penetrating shortwave ! heating that hits the bottom and will be redistributed through - ! the water column [degC H ~> degC m or degC kg m-2] + ! the water column [C H ~> degC m or degC kg m-2] real :: SW_trans ! fraction of shortwave radiation that is not ! absorbed in a layer [nondim] real :: unabsorbed ! fraction of the shortwave radiation that @@ -600,13 +600,13 @@ subroutine absorbRemainingSW(G, GV, US, h, opacity_band, nsw, optics, j, dt, H_l real :: exp_OD ! exp(-opt_depth) [nondim] real :: heat_bnd ! heating due to absorption in the current ! layer by the current band, including any piece that - ! is moved upward [degC H ~> degC m or degC kg m-2] + ! is moved upward [C H ~> degC m or degC kg m-2] real :: SWa ! fraction of the absorbed shortwave that is ! moved to layers above with adjustAbsorptionProfile [nondim] real :: coSWa_frac ! The fraction of SWa that is actually moved upward. real :: min_SW_heat ! A minimum remaining shortwave heating within a timestep that will be simply ! absorbed in the next layer for computational efficiency, instead of - ! continuing to penetrate [degC H ~> degC m or degC kg m-2]. + ! continuing to penetrate [C H ~> degC m or degC kg m-2]. real :: I_Habs ! The inverse of the absorption length for a minimal flux [H-1 ~> m-1 or m2 kg-1] real :: epsilon ! A small thickness that must remain in each ! layer, and which will not be subject to heating [H ~> m or kg m-2] @@ -811,21 +811,21 @@ subroutine sumSWoverBands(G, GV, US, h, nsw, optics, j, dt, & !! radiation is absorbed in the ocean water column. real, dimension(max(nsw,1),SZI_(G)), intent(in) :: iPen_SW_bnd !< The incident penetrating shortwave !! in each band at the sea surface; size nsw x SZI_(G) - !! [degC H ~> degC m or degC kg m-2]. + !! [C H ~> degC m or degC kg m-2]. real, dimension(SZI_(G),SZK_(GV)+1), & intent(inout) :: netPen !< Net penetrating shortwave heat flux at each !! interface, summed across all bands - !! [degC H ~> degC m or degC kg m-2]. + !! [C H ~> degC m or degC kg m-2]. ! Local variables real :: h_heat(SZI_(G)) ! thickness of the water column that receives ! remaining shortwave radiation [H ~> m or kg m-2]. real :: Pen_SW_rem(SZI_(G)) ! sum across all wavelength bands of the ! penetrating shortwave heating that hits the bottom ! and will be redistributed through the water column - ! [degC H ~> degC m or degC kg m-2] + ! [C H ~> degC m or degC kg m-2] real, dimension(max(nsw,1),SZI_(G)) :: Pen_SW_bnd ! The remaining penetrating shortwave radiation - ! in each band, initially iPen_SW_bnd [degC H ~> degC m or degC kg m-2] + ! in each band, initially iPen_SW_bnd [C H ~> degC m or degC kg m-2] real :: SW_trans ! fraction of shortwave radiation not ! absorbed in a layer [nondim] real :: unabsorbed ! fraction of the shortwave radiation @@ -834,7 +834,7 @@ subroutine sumSWoverBands(G, GV, US, h, nsw, optics, j, dt, & ! surface fluxes start to be limited [H-1 ~> m-1 or m2 kg-1] real :: min_SW_heat ! A minimum remaining shortwave heating within a timestep that will be simply ! absorbed in the next layer for computational efficiency, instead of - ! continuing to penetrate [degC H ~> degC m or degC kg m-2]. + ! continuing to penetrate [C H ~> degC m or degC kg m-2]. real :: I_Habs ! The inverse of the absorption length for a minimal flux [H-1 ~> m-1 or m2 kg-1] real :: h_min_heat ! minimum thickness layer that should get heated [H ~> m or kg m-2] real :: opt_depth ! optical depth of a layer [nondim] @@ -1070,7 +1070,7 @@ subroutine opacity_init(Time, G, GV, US, param_file, diag, CS, optics) "the next sufficiently thick layers for computational efficiency, instead of "//& "continuing to penetrate. The default, 2.5e-11 degC m s-1, is about 1e-4 W m-2 "//& "or 0.08 degC m century-1, but 0 is also a valid value.", & - default=2.5e-11, units="degC m s-1", scale=GV%m_to_H*US%T_to_s) + default=2.5e-11, units="degC m s-1", scale=US%degC_to_C*GV%m_to_H*US%T_to_s) if (optics%answers_2018) then ; PenSW_minthick_dflt = 0.001 ; else ; PenSW_minthick_dflt = 1.0 ; endif call get_param(param_file, mdl, "PEN_SW_ABSORB_MINTHICK", PenSW_absorb_minthick, & diff --git a/src/parameterizations/vertical/MOM_regularize_layers.F90 b/src/parameterizations/vertical/MOM_regularize_layers.F90 index 45b21eb1ab..3791ad26aa 100644 --- a/src/parameterizations/vertical/MOM_regularize_layers.F90 +++ b/src/parameterizations/vertical/MOM_regularize_layers.F90 @@ -133,12 +133,12 @@ subroutine regularize_surface(h, tv, dt, ea, eb, G, GV, US, CS) e_filt, e_2d ! The interface depths [H ~> m or kg m-2], positive upward. real, dimension(SZI_(G),SZK_(GV)) :: & h_2d, & ! A 2-d version of h [H ~> m or kg m-2]. - T_2d, & ! A 2-d version of tv%T [degC]. - S_2d, & ! A 2-d version of tv%S [ppt]. + T_2d, & ! A 2-d version of tv%T [C ~> degC]. + S_2d, & ! A 2-d version of tv%S [S ~> ppt]. Rcv, & ! A 2-d version of the coordinate density [R ~> kg m-3]. h_2d_init, & ! The initial value of h_2d [H ~> m or kg m-2]. - T_2d_init, & ! THe initial value of T_2d [degC]. - S_2d_init, & ! The initial value of S_2d [ppt]. + T_2d_init, & ! THe initial value of T_2d [C ~> degC]. + S_2d_init, & ! The initial value of S_2d [S ~> ppt]. d_eb, & ! The downward increase across a layer in the entrainment from ! below [H ~> m or kg m-2]. The sign convention is that positive values of ! d_eb correspond to a gain in mass by a layer by upward motion. @@ -164,7 +164,9 @@ subroutine regularize_surface(h, tv, dt, ea, eb, G, GV, US, CS) real :: h_neglect ! A thickness that is so small it is usually lost ! in roundoff and can be neglected [H ~> m or kg m-2]. real, dimension(SZK_(GV)+1) :: & - int_flux, int_Tflux, int_Sflux, int_Rflux + int_flux, & ! Mass flux across the interfaces [H ~> m or kg m-2] + int_Tflux, & ! Temperature flux across the interfaces [C H ~> degC m or degC kg m-2] + int_Sflux ! Salinity flux across the interfaces [S H ~> ppt m or ppt kg m-2] real :: h_add real :: h_det_tot real :: max_def_rat @@ -466,7 +468,7 @@ subroutine regularize_surface(h, tv, dt, ea, eb, G, GV, US, CS) k1 = 1 ; k2 = 1 int_top = 0.0 do k=1,nkmb+1 - int_flux(k) = 0.0 ; int_Rflux(k) = 0.0 + int_flux(k) = 0.0 int_Tflux(k) = 0.0 ; int_Sflux(k) = 0.0 enddo do k=1,2*nkmb diff --git a/src/parameterizations/vertical/MOM_set_diffusivity.F90 b/src/parameterizations/vertical/MOM_set_diffusivity.F90 index fd7335fd0a..20f92af86b 100644 --- a/src/parameterizations/vertical/MOM_set_diffusivity.F90 +++ b/src/parameterizations/vertical/MOM_set_diffusivity.F90 @@ -243,7 +243,7 @@ subroutine set_diffusivity(u, v, h, u_h, v_h, tv, fluxes, optics, visc, dt, Kd_i type(diffusivity_diags) :: dd ! structure with arrays of available diags real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: & - T_f, S_f ! Temperature and salinity [degC] and [ppt] with properties in massless layers + T_f, S_f ! Temperature and salinity [C ~> degC] and [S ~> ppt] with properties in massless layers ! filled vertically by diffusion or the properties after full convective adjustment. real, dimension(SZI_(G),SZK_(GV)) :: & @@ -375,14 +375,14 @@ subroutine set_diffusivity(u, v, h, u_h, v_h, tv, fluxes, optics, visc, dt, Kd_i ! Smooth the properties through massless layers. if (use_EOS) then if (CS%debug) then - call hchksum(tv%T, "before vert_fill_TS tv%T",G%HI) - call hchksum(tv%S, "before vert_fill_TS tv%S",G%HI) + call hchksum(tv%T, "before vert_fill_TS tv%T", G%HI, scale=US%C_to_degC) + call hchksum(tv%S, "before vert_fill_TS tv%S", G%HI, scale=US%S_to_ppt) call hchksum(h, "before vert_fill_TS h",G%HI, scale=GV%H_to_m) endif call vert_fill_TS(h, tv%T, tv%S, kappa_dt_fill, T_f, S_f, G, GV, larger_h_denom=.true.) if (CS%debug) then - call hchksum(tv%T, "after vert_fill_TS tv%T",G%HI) - call hchksum(tv%S, "after vert_fill_TS tv%S",G%HI) + call hchksum(tv%T, "after vert_fill_TS tv%T", G%HI, scale=US%C_to_degC) + call hchksum(tv%S, "after vert_fill_TS tv%S", G%HI, scale=US%S_to_ppt) call hchksum(h, "after vert_fill_TS h",G%HI, scale=GV%H_to_m) endif endif @@ -877,10 +877,10 @@ subroutine find_N2(h, tv, T_f, S_f, fluxes, j, G, GV, US, CS, dRho_int, & !! thermodynamic fields. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: T_f !< layer temperature with the values in massless layers - !! filled vertically by diffusion [degC]. + !! filled vertically by diffusion [C ~> degC]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: S_f !< Layer salinities with values in massless - !! layers filled vertically by diffusion [ppt]. + !! layers filled vertically by diffusion [S ~> ppt]. type(forcing), intent(in) :: fluxes !< A structure of thermodynamic surface fluxes integer, intent(in) :: j !< j-index of row to work on type(set_diffusivity_CS), pointer :: CS !< Diffusivity control structure @@ -895,13 +895,13 @@ subroutine find_N2(h, tv, T_f, S_f, fluxes, j, G, GV, US, CS, dRho_int, & ! Local variables real, dimension(SZI_(G),SZK_(GV)+1) :: & dRho_int_unfilt, & ! unfiltered density differences across interfaces [R ~> kg m-3] - dRho_dT, & ! partial derivative of density wrt temp [R degC-1 ~> kg m-3 degC-1] - dRho_dS ! partial derivative of density wrt saln [R ppt-1 ~> kg m-3 ppt-1] + dRho_dT, & ! partial derivative of density wrt temp [R C-1 ~> kg m-3 degC-1] + dRho_dS ! partial derivative of density wrt saln [R S-1 ~> kg m-3 ppt-1] real, dimension(SZI_(G)) :: & pres, & ! pressure at each interface [R L2 T-2 ~> Pa] - Temp_int, & ! temperature at each interface [degC] - Salin_int, & ! salinity at each interface [ppt] + Temp_int, & ! temperature at each interface [C ~>degC] + Salin_int, & ! salinity at each interface [S ~> ppt] drho_bot, & ! A density difference [R ~> kg m-3] h_amp, & ! The topographic roughness amplitude [Z ~> m]. hb, & ! The thickness of the bottom layer [Z ~> m]. @@ -1047,10 +1047,10 @@ subroutine double_diffusion(tv, h, T_f, S_f, j, G, GV, US, CS, Kd_T_dd, Kd_S_dd) intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: T_f !< layer temperatures with the values in massless layers - !! filled vertically by diffusion [degC]. + !! filled vertically by diffusion [C ~> degC]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: S_f !< Layer salinities with values in massless - !! layers filled vertically by diffusion [ppt]. + !! layers filled vertically by diffusion [S ~> ppt]. integer, intent(in) :: j !< Meridional index upon which to work. type(set_diffusivity_CS), pointer :: CS !< Module control structure. real, dimension(SZI_(G),SZK_(GV)+1), & @@ -1061,11 +1061,11 @@ subroutine double_diffusion(tv, h, T_f, S_f, j, G, GV, US, CS, Kd_T_dd, Kd_S_dd) !! diffusivity for saln [Z2 T-1 ~> m2 s-1]. real, dimension(SZI_(G)) :: & - dRho_dT, & ! partial derivatives of density wrt temp [R degC-1 ~> kg m-3 degC-1] - dRho_dS, & ! partial derivatives of density wrt saln [R ppt-1 ~> kg m-3 ppt-1] + dRho_dT, & ! partial derivatives of density wrt temp [R C-1 ~> kg m-3 degC-1] + dRho_dS, & ! partial derivatives of density wrt saln [R S-1 ~> kg m-3 ppt-1] pres, & ! pressure at each interface [R L2 T-2 ~> Pa] - Temp_int, & ! temperature at interfaces [degC] - Salin_int ! Salinity at interfaces [ppt] + Temp_int, & ! temperature at interfaces [C ~> degC] + Salin_int ! Salinity at interfaces [S ~> ppt] real :: alpha_dT ! density difference between layers due to temp diffs [R ~> kg m-3] real :: beta_dS ! density difference between layers due to saln diffs [R ~> kg m-3] diff --git a/src/parameterizations/vertical/MOM_set_viscosity.F90 b/src/parameterizations/vertical/MOM_set_viscosity.F90 index 761a77b399..7934b6b019 100644 --- a/src/parameterizations/vertical/MOM_set_viscosity.F90 +++ b/src/parameterizations/vertical/MOM_set_viscosity.F90 @@ -139,13 +139,13 @@ subroutine set_viscous_BBL(u, v, h, tv, visc, G, GV, US, CS, pbv) real, dimension(SZIB_(G)) :: & ustar, & ! The bottom friction velocity [Z T-1 ~> m s-1]. T_EOS, & ! The temperature used to calculate the partial derivatives - ! of density with T and S [degC]. + ! of density with T and S [C ~> degC]. S_EOS, & ! The salinity used to calculate the partial derivatives - ! of density with T and S [ppt]. + ! of density with T and S [S ~> ppt]. dR_dT, & ! Partial derivative of the density in the bottom boundary - ! layer with temperature [R degC-1 ~> kg m-3 degC-1]. + ! layer with temperature [R C-1 ~> kg m-3 degC-1]. dR_dS, & ! Partial derivative of the density in the bottom boundary - ! layer with salinity [R ppt-1 ~> kg m-3 ppt-1]. + ! layer with salinity [R S-1 ~> kg m-3 ppt-1]. press ! The pressure at which dR_dT and dR_dS are evaluated [R L2 T-2 ~> Pa]. real :: htot ! Sum of the layer thicknesses up to some point [H ~> m or kg m-2]. real :: htot_vel ! Sum of the layer thicknesses up to some point [H ~> m or kg m-2]. @@ -167,9 +167,9 @@ subroutine set_viscous_BBL(u, v, h, tv, visc, G, GV, US, CS, pbv) h_vel, & ! Arithmetic mean of the layer thicknesses adjacent to a ! velocity point [H ~> m or kg m-2]. T_vel, & ! Arithmetic mean of the layer temperatures adjacent to a - ! velocity point [degC]. + ! velocity point [C ~> degC]. S_vel, & ! Arithmetic mean of the layer salinities adjacent to a - ! velocity point [ppt]. + ! velocity point [S ~> ppt]. Rml_vel ! Arithmetic mean of the layer coordinate densities adjacent ! to a velocity point [R ~> kg m-3]. @@ -201,8 +201,8 @@ subroutine set_viscous_BBL(u, v, h, tv, visc, G, GV, US, CS, pbv) ! the near-bottom velocity magnitude [H ~> m or kg m-2]. real :: hutot ! Running sum of thicknesses times the ! velocity magnitudes [H L T-1 ~> m2 s-1 or kg m-1 s-1]. - real :: Thtot ! Running sum of thickness times temperature [degC H ~> degC m or degC kg m-2]. - real :: Shtot ! Running sum of thickness times salinity [ppt H ~> ppt m or ppt kg m-2]. + real :: Thtot ! Running sum of thickness times temperature [C H ~> degC m or degC kg m-2]. + real :: Shtot ! Running sum of thickness times salinity [S H ~> ppt m or ppt kg m-2]. real :: hweight ! The thickness of a layer that is within Hbbl ! of the bottom [H ~> m or kg m-2]. real :: v_at_u, u_at_v ! v at a u point or vice versa [L T-1 ~> m s-1]. @@ -294,8 +294,8 @@ subroutine set_viscous_BBL(u, v, h, tv, visc, G, GV, US, CS, pbv) if (CS%debug) then call uvchksum("Start set_viscous_BBL [uv]", u, v, G%HI, haloshift=1, scale=US%L_T_to_m_s) call hchksum(h,"Start set_viscous_BBL h", G%HI, haloshift=1, scale=GV%H_to_m) - if (associated(tv%T)) call hchksum(tv%T, "Start set_viscous_BBL T", G%HI, haloshift=1) - if (associated(tv%S)) call hchksum(tv%S, "Start set_viscous_BBL S", G%HI, haloshift=1) + if (associated(tv%T)) call hchksum(tv%T, "Start set_viscous_BBL T", G%HI, haloshift=1, scale=US%C_to_degC) + if (associated(tv%S)) call hchksum(tv%S, "Start set_viscous_BBL S", G%HI, haloshift=1, scale=US%S_to_ppt) endif use_BBL_EOS = associated(tv%eqn_of_state) .and. CS%BBL_use_EOS @@ -1157,9 +1157,9 @@ subroutine set_viscous_ML(u, v, h, tv, forces, visc, dt, G, GV, US, CS) htot, & ! The total depth of the layers being that are within the ! surface mixed layer [H ~> m or kg m-2]. Thtot, & ! The integrated temperature of layers that are within the - ! surface mixed layer [H degC ~> m degC or kg degC m-2]. + ! surface mixed layer [H C ~> m degC or kg degC m-2]. Shtot, & ! The integrated salt of layers that are within the - ! surface mixed layer [H ppt ~> m ppt or kg ppt m-2]. + ! surface mixed layer [H S ~> m ppt or kg ppt m-2]. Rhtot, & ! The integrated density of layers that are within the surface mixed layer ! [H R ~> kg m-2 or kg2 m-5]. Rhtot is only used if no ! equation of state is used. @@ -1167,13 +1167,13 @@ subroutine set_viscous_ML(u, v, h, tv, forces, visc, dt, G, GV, US, CS) vhtot, & ! the surface mixed layer [H L T-1 ~> m2 s-1 or kg m-1 s-1]. Idecay_len_TKE, & ! The inverse of a turbulence decay length scale [H-1 ~> m-1 or m2 kg-1]. dR_dT, & ! Partial derivative of the density at the base of layer nkml - ! (roughly the base of the mixed layer) with temperature [R degC-1 ~> kg m-3 degC-1]. + ! (roughly the base of the mixed layer) with temperature [R C-1 ~> kg m-3 degC-1]. dR_dS, & ! Partial derivative of the density at the base of layer nkml - ! (roughly the base of the mixed layer) with salinity [R ppt-1 ~> kg m-3 ppt-1]. + ! (roughly the base of the mixed layer) with salinity [R S-1 ~> kg m-3 ppt-1]. ustar, & ! The surface friction velocity under ice shelves [Z T-1 ~> m s-1]. press, & ! The pressure at which dR_dT and dR_dS are evaluated [R L2 T-2 ~> Pa]. - T_EOS, & ! The potential temperature at which dR_dT and dR_dS are evaluated [degC] - S_EOS ! The salinity at which dR_dT and dR_dS are evaluated [ppt]. + T_EOS, & ! The potential temperature at which dR_dT and dR_dS are evaluated [C ~> degC] + S_EOS ! The salinity at which dR_dT and dR_dS are evaluated [S ~> ppt]. real, dimension(SZIB_(G),SZJ_(G)) :: & mask_u ! A mask that disables any contributions from u points that ! are land or past open boundary conditions [nondim], 0 or 1. @@ -1201,8 +1201,8 @@ subroutine set_viscous_ML(u, v, h, tv, forces, visc, dt, G, GV, US, CS) real :: hlay ! The layer thickness at velocity points [H ~> m or kg m-2]. real :: I_2hlay ! 1 / 2*hlay [H-1 ~> m-1 or m2 kg-1]. - real :: T_lay ! The layer temperature at velocity points [degC]. - real :: S_lay ! The layer salinity at velocity points [ppt]. + real :: T_lay ! The layer temperature at velocity points [C ~> degC]. + real :: S_lay ! The layer salinity at velocity points [S ~> ppt]. real :: Rlay ! The layer potential density at velocity points [R ~> kg m-3]. real :: Rlb ! The potential density of the layer below [R ~> kg m-3]. real :: v_at_u ! The meridonal velocity at a zonal velocity point [L T-1 ~> m s-1]. diff --git a/src/tracer/MOM_generic_tracer.F90 b/src/tracer/MOM_generic_tracer.F90 index 5eb286ce7d..e454a9a4bb 100644 --- a/src/tracer/MOM_generic_tracer.F90 +++ b/src/tracer/MOM_generic_tracer.F90 @@ -495,25 +495,26 @@ subroutine MOM_generic_tracer_column_physics(h_old, h_new, ea, eb, fluxes, Hml, surface_field(i,j) = tv%S(i,j,1) dz_ml(i,j) = US%Z_to_m * Hml(i,j) enddo ; enddo - sosga = global_area_mean(surface_field, G) + sosga = global_area_mean(surface_field, G, scale=US%S_to_ppt) ! !Calculate tendencies (i.e., field changes at dt) from the sources / sinks ! if ((G%US%L_to_m == 1.0) .and. (G%US%s_to_T == 1.0) .and. (G%US%Z_to_m == 1.0) .and. & - (G%US%Q_to_J_kg == 1.0) .and. (G%US%RZ_to_kg_m2 == 1.0)) then + (G%US%Q_to_J_kg == 1.0) .and. (G%US%RZ_to_kg_m2 == 1.0) .and. & + (US%C_to_degC == 1.0) .and. (US%S_to_ppt == 1.0)) then ! Avoid unnecessary copies when no unit conversion is needed. call generic_tracer_source(tv%T, tv%S, rho_dzt, dzt, dz_ml, G%isd, G%jsd, 1, dt, & G%areaT, get_diag_time_end(CS%diag), & optics%nbands, optics%max_wavelength_band, optics%sw_pen_band, optics%opacity_band, & internal_heat=tv%internal_heat, frunoff=fluxes%frunoff, sosga=sosga) else - call generic_tracer_source(tv%T, tv%S, rho_dzt, dzt, dz_ml, G%isd, G%jsd, 1, dt, & + call generic_tracer_source(US%C_to_degC*tv%T, US%S_to_ppt*tv%S, rho_dzt, dzt, dz_ml, G%isd, G%jsd, 1, dt, & G%US%L_to_m**2*G%areaT(:,:), get_diag_time_end(CS%diag), & optics%nbands, optics%max_wavelength_band, & sw_pen_band=G%US%QRZ_T_to_W_m2*optics%sw_pen_band(:,:,:), & opacity_band=G%US%m_to_Z*optics%opacity_band(:,:,:,:), & - internal_heat=G%US%RZ_to_kg_m2*tv%internal_heat(:,:), & + internal_heat=G%US%RZ_to_kg_m2*US%C_to_degC*tv%internal_heat(:,:), & frunoff=G%US%RZ_T_to_kg_m2s*fluxes%frunoff(:,:), sosga=sosga) endif diff --git a/src/tracer/MOM_neutral_diffusion.F90 b/src/tracer/MOM_neutral_diffusion.F90 index f21bc9fa84..a8e08d8cab 100644 --- a/src/tracer/MOM_neutral_diffusion.F90 +++ b/src/tracer/MOM_neutral_diffusion.F90 @@ -74,18 +74,18 @@ module MOM_neutral_diffusion real, allocatable, dimension(:,:,:,:) :: ppoly_coeffs_T !< Polynomial coefficients for temperature real, allocatable, dimension(:,:,:,:) :: ppoly_coeffs_S !< Polynomial coefficients for salinity ! Variables needed for continuous reconstructions - real, allocatable, dimension(:,:,:) :: dRdT !< dRho/dT [R degC-1 ~> kg m-3 degC-1] at interfaces - real, allocatable, dimension(:,:,:) :: dRdS !< dRho/dS [R ppt-1 ~> kg m-3 ppt-1] at interfaces - real, allocatable, dimension(:,:,:) :: Tint !< Interface T [degC] - real, allocatable, dimension(:,:,:) :: Sint !< Interface S [ppt] + real, allocatable, dimension(:,:,:) :: dRdT !< dRho/dT [R C-1 ~> kg m-3 degC-1] at interfaces + real, allocatable, dimension(:,:,:) :: dRdS !< dRho/dS [R S-1 ~> kg m-3 ppt-1] at interfaces + real, allocatable, dimension(:,:,:) :: Tint !< Interface T [C ~> degC] + real, allocatable, dimension(:,:,:) :: Sint !< Interface S [S ~> ppt] real, allocatable, dimension(:,:,:) :: Pint !< Interface pressure [R L2 T-2 ~> Pa] ! Variables needed for discontinuous reconstructions - real, allocatable, dimension(:,:,:,:) :: T_i !< Top edge reconstruction of temperature [degC] - real, allocatable, dimension(:,:,:,:) :: S_i !< Top edge reconstruction of salinity [ppt] + real, allocatable, dimension(:,:,:,:) :: T_i !< Top edge reconstruction of temperature [C ~> degC] + real, allocatable, dimension(:,:,:,:) :: S_i !< Top edge reconstruction of salinity [S ~> ppt] real, allocatable, dimension(:,:,:,:) :: P_i !< Interface pressures [R L2 T-2 ~> Pa] - real, allocatable, dimension(:,:,:,:) :: dRdT_i !< dRho/dT [R degC-1 ~> kg m-3 degC-1] at top edge - real, allocatable, dimension(:,:,:,:) :: dRdS_i !< dRho/dS [R ppt-1 ~> kg m-3 ppt-1] at top edge - integer, allocatable, dimension(:,:) :: ns !< Number of interfacs in a column + real, allocatable, dimension(:,:,:,:) :: dRdT_i !< dRho/dT [R C-1 ~> kg m-3 degC-1] at top edge + real, allocatable, dimension(:,:,:,:) :: dRdS_i !< dRho/dS [R S-1 ~> kg m-3 ppt-1] at top edge + integer, allocatable, dimension(:,:) :: ns !< Number of interfaces in a column logical, allocatable, dimension(:,:,:) :: stable_cell !< True if the cell is stably stratified wrt to the next cell real :: R_to_kg_m3 = 1.0 !< A rescaling factor translating density to kg m-3 for !! use in diagnostic messages [kg m-3 R-1 ~> 1]. @@ -286,8 +286,8 @@ subroutine neutral_diffusion_calc_coeffs(G, GV, US, h, T, S, CS, p_surf) type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: T !< Potential temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: S !< Salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: T !< Potential temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: S !< Salinity [S ~> ppt] type(neutral_diffusion_CS), pointer :: CS !< Neutral diffusion control structure real, dimension(SZI_(G),SZJ_(G)), optional, intent(in) :: p_surf !< Surface pressure to include in pressures used !! for equation of state calculations [R L2 T-2 ~> Pa] @@ -372,7 +372,7 @@ subroutine neutral_diffusion_calc_coeffs(G, GV, US, h, T, S, CS, p_surf) enddo ; enddo ; enddo ! Pressures at the interfaces, this is redundant as P_i(k,1) = P_i(k-1,2) however retain this - ! for now to ensure consitency of indexing for diiscontinuous reconstructions + ! for now to ensure consistency of indexing for discontinuous reconstructions if (.not. CS%continuous_reconstruction) then if (present(p_surf)) then do j=G%jsc-1,G%jec+1 ; do i=G%isc-1,G%iec+1 @@ -805,9 +805,9 @@ real function ppm_ave(xL, xR, aL, aR, aMean) a6 = 3. * a6o3 if (dx<0.) then - stop 'ppm_ave: dx<0 should not happend!' + stop 'ppm_ave: dx<0 should not happened!' elseif (dx>1.) then - stop 'ppm_ave: dx>1 should not happend!' + stop 'ppm_ave: dx>1 should not happened!' elseif (dx==0.) then ppm_ave = aL + ( aR - aL ) * xR + a6 * xR * ( 1. - xR ) else @@ -954,15 +954,15 @@ subroutine find_neutral_surface_positions_continuous(nk, Pl, Tl, Sl, dRdTl, dRdS dRdTr, dRdSr, PoL, PoR, KoL, KoR, hEff, bl_kl, bl_kr, bl_zl, bl_zr) integer, intent(in) :: nk !< Number of levels real, dimension(nk+1), intent(in) :: Pl !< Left-column interface pressure [R L2 T-2 ~> Pa] or other units - real, dimension(nk+1), intent(in) :: Tl !< Left-column interface potential temperature [degC] - real, dimension(nk+1), intent(in) :: Sl !< Left-column interface salinity [ppt] - real, dimension(nk+1), intent(in) :: dRdTl !< Left-column dRho/dT [R degC-1 ~> kg m-3 degC-1] - real, dimension(nk+1), intent(in) :: dRdSl !< Left-column dRho/dS [R ppt-1 ~> kg m-3 ppt-1] + real, dimension(nk+1), intent(in) :: Tl !< Left-column interface potential temperature [C ~> degC] + real, dimension(nk+1), intent(in) :: Sl !< Left-column interface salinity [S ~> ppt] + real, dimension(nk+1), intent(in) :: dRdTl !< Left-column dRho/dT [R C-1 ~> kg m-3 degC-1] + real, dimension(nk+1), intent(in) :: dRdSl !< Left-column dRho/dS [R S-1 ~> kg m-3 ppt-1] real, dimension(nk+1), intent(in) :: Pr !< Right-column interface pressure [R L2 T-2 ~> Pa] or other units - real, dimension(nk+1), intent(in) :: Tr !< Right-column interface potential temperature [degC] - real, dimension(nk+1), intent(in) :: Sr !< Right-column interface salinity [ppt] - real, dimension(nk+1), intent(in) :: dRdTr !< Left-column dRho/dT [R degC-1 ~> kg m-3 degC-1] - real, dimension(nk+1), intent(in) :: dRdSr !< Left-column dRho/dS [R ppt-1 ~> kg m-3 ppt-1] + real, dimension(nk+1), intent(in) :: Tr !< Right-column interface potential temperature [C ~> degC] + real, dimension(nk+1), intent(in) :: Sr !< Right-column interface salinity [S ~> ppt] + real, dimension(nk+1), intent(in) :: dRdTr !< Left-column dRho/dT [R C-1 ~> kg m-3 degC-1] + real, dimension(nk+1), intent(in) :: dRdSr !< Left-column dRho/dS [R S-1 ~> kg m-3 ppt-1] real, dimension(2*nk+2), intent(inout) :: PoL !< Fractional position of neutral surface within !! layer KoL of left column [nondim] real, dimension(2*nk+2), intent(inout) :: PoR !< Fractional position of neutral surface within @@ -1199,7 +1199,7 @@ real function interpolate_for_nondim_position(dRhoNeg, Pneg, dRhoPos, Ppos) end function interpolate_for_nondim_position !> Higher order version of find_neutral_surface_positions. Returns positions within left/right columns -!! of combined interfaces using intracell reconstructions of T/S. Note that the polynomial reconstrcutions +!! of combined interfaces using intracell reconstructions of T/S. Note that the polynomial reconstructions !! of T and S are optional to aid with unit testing, but will always be passed otherwise subroutine find_neutral_surface_positions_discontinuous(CS, nk, & Pres_l, hcol_l, Tl, Sl, ppoly_T_l, ppoly_S_l, stable_l, & @@ -1211,18 +1211,21 @@ subroutine find_neutral_surface_positions_discontinuous(CS, nk, & real, dimension(nk,2), intent(in) :: Pres_l !< Left-column interface pressure [R L2 T-2 ~> Pa] real, dimension(nk), intent(in) :: hcol_l !< Left-column layer thicknesses [H ~> m or kg m-2] !! or other units - real, dimension(nk,2), intent(in) :: Tl !< Left-column top interface potential temperature [degC] - real, dimension(nk,2), intent(in) :: Sl !< Left-column top interface salinity [ppt] - real, dimension(:,:), intent(in) :: ppoly_T_l !< Left-column coefficients of T reconstruction [degC] - real, dimension(:,:), intent(in) :: ppoly_S_l !< Left-column coefficients of S reconstruction [ppt] + real, dimension(nk,2), intent(in) :: Tl !< Left-column top interface potential + !! temperature [C ~> degC] + real, dimension(nk,2), intent(in) :: Sl !< Left-column top interface salinity [S ~> ppt] + real, dimension(:,:), intent(in) :: ppoly_T_l !< Left-column coefficients of T reconstruction [C ~> degC] + real, dimension(:,:), intent(in) :: ppoly_S_l !< Left-column coefficients of S reconstruction [S ~> ppt] logical, dimension(nk), intent(in) :: stable_l !< True where the left-column is stable real, dimension(nk,2), intent(in) :: Pres_r !< Right-column interface pressure [R L2 T-2 ~> Pa] real, dimension(nk), intent(in) :: hcol_r !< Left-column layer thicknesses [H ~> m or kg m-2] !! or other units - real, dimension(nk,2), intent(in) :: Tr !< Right-column top interface potential temperature [degC] - real, dimension(nk,2), intent(in) :: Sr !< Right-column top interface salinity [ppt] - real, dimension(:,:), intent(in) :: ppoly_T_r !< Right-column coefficients of T reconstruction [degC] - real, dimension(:,:), intent(in) :: ppoly_S_r !< Right-column coefficients of S reconstruction [ppt] + real, dimension(nk,2), intent(in) :: Tr !< Right-column top interface potential + !! temperature [C ~> degC] + real, dimension(nk,2), intent(in) :: Sr !< Right-column top interface salinity [S ~> ppt] + real, dimension(:,:), intent(in) :: ppoly_T_r !< Right-column coefficients of T + !! reconstruction [C ~> degC] + real, dimension(:,:), intent(in) :: ppoly_S_r !< Right-column coefficients of S reconstruction [S ~> ppt] logical, dimension(nk), intent(in) :: stable_r !< True where the right-column is stable real, dimension(4*nk), intent(inout) :: PoL !< Fractional position of neutral surface within !! layer KoL of left column [nondim] @@ -1233,9 +1236,9 @@ subroutine find_neutral_surface_positions_discontinuous(CS, nk, & real, dimension(4*nk-1), intent(inout) :: hEff !< Effective thickness between two neutral surfaces !! [H ~> m or kg m-2] or other units taken from hcol_l real, optional, intent(in) :: zeta_bot_L!< Non-dimensional distance to where the boundary layer - !! intersetcs the cell (left) [nondim] + !! intersects the cell (left) [nondim] real, optional, intent(in) :: zeta_bot_R!< Non-dimensional distance to where the boundary layer - !! intersetcs the cell (right) [nondim] + !! intersects the cell (right) [nondim] integer, optional, intent(in) :: k_bot_L !< k-index for the boundary layer (left) [nondim] integer, optional, intent(in) :: k_bot_R !< k-index for the boundary layer (right) [nondim] @@ -1438,8 +1441,8 @@ end subroutine find_neutral_surface_positions_discontinuous subroutine mark_unstable_cells(CS, nk, T, S, P, stable_cell) type(neutral_diffusion_CS), intent(inout) :: CS !< Neutral diffusion control structure integer, intent(in) :: nk !< Number of levels in a column - real, dimension(nk,2), intent(in) :: T !< Temperature at interfaces [degC] - real, dimension(nk,2), intent(in) :: S !< Salinity at interfaces [ppt] + real, dimension(nk,2), intent(in) :: T !< Temperature at interfaces [C ~> degC] + real, dimension(nk,2), intent(in) :: S !< Salinity at interfaces [S ~> ppt] real, dimension(nk,2), intent(in) :: P !< Pressure at interfaces [R L2 T-2 ~> Pa] logical, dimension(nk), intent( out) :: stable_cell !< True if this cell is unstably stratified @@ -1460,25 +1463,27 @@ real function search_other_column(CS, ksurf, pos_last, T_from, S_from, P_from, T integer, intent(in ) :: ksurf !< Current index of neutral surface real, intent(in ) :: pos_last !< Last position within the current layer, used as the lower !! bound in the root finding algorithm [nondim] - real, intent(in ) :: T_from !< Temperature at the searched from interface [degC] - real, intent(in ) :: S_from !< Salinity at the searched from interface [ppt] + real, intent(in ) :: T_from !< Temperature at the searched from interface [C ~> degC] + real, intent(in ) :: S_from !< Salinity at the searched from interface [S ~> ppt] real, intent(in ) :: P_from !< Pressure at the searched from interface [R L2 T-2 ~> Pa] - real, intent(in ) :: T_top !< Temperature at the searched to top interface [degC] - real, intent(in ) :: S_top !< Salinity at the searched to top interface [ppt] + real, intent(in ) :: T_top !< Temperature at the searched to top interface [C ~> degC] + real, intent(in ) :: S_top !< Salinity at the searched to top interface [S ~> ppt] real, intent(in ) :: P_top !< Pressure at the searched to top interface [R L2 T-2 ~> Pa] !! interface [R L2 T-2 ~> Pa] - real, intent(in ) :: T_bot !< Temperature at the searched to bottom interface [degC] - real, intent(in ) :: S_bot !< Salinity at the searched to bottom interface [ppt] + real, intent(in ) :: T_bot !< Temperature at the searched to bottom interface [C ~> degC] + real, intent(in ) :: S_bot !< Salinity at the searched to bottom interface [S ~> ppt] real, intent(in ) :: P_bot !< Pressure at the searched to bottom !! interface [R L2 T-2 ~> Pa] - real, dimension(:), intent(in ) :: T_poly !< Temperature polynomial reconstruction coefficients [degC] - real, dimension(:), intent(in ) :: S_poly !< Salinity polynomial reconstruction coefficients [ppt] + real, dimension(:), intent(in ) :: T_poly !< Temperature polynomial reconstruction + !! coefficients [C ~> degC] + real, dimension(:), intent(in ) :: S_poly !< Salinity polynomial reconstruction + !! coefficients [S ~> ppt] ! Local variables real :: dRhotop, dRhobot ! Density differences [R ~> kg m-3] - real :: dRdT_top, dRdT_bot, dRdT_from ! Partial derivatives of density with temperature [R degC-1 ~> kg m-3 degC-1] - real :: dRdS_top, dRdS_bot, dRdS_from ! Partial derivatives of density with salinity [R ppt-1 ~> kg m-3 ppt-1] + real :: dRdT_top, dRdT_bot, dRdT_from ! Partial derivatives of density with temperature [R C-1 ~> kg m-3 degC-1] + real :: dRdS_top, dRdS_bot, dRdS_from ! Partial derivatives of density with salinity [R S-1 ~> kg m-3 ppt-1] - ! Calculate the differencei in density at the tops or the bottom + ! Calculate the difference in density at the tops or the bottom if (CS%neutral_pos_method == 1 .or. CS%neutral_pos_method == 3) then call calc_delta_rho_and_derivs(CS, T_top, S_top, P_top, T_from, S_from, P_from, dRhoTop) call calc_delta_rho_and_derivs(CS, T_bot, S_bot, P_bot, T_from, S_from, P_from, dRhoBot) @@ -1511,7 +1516,7 @@ real function search_other_column(CS, ksurf, pos_last, T_from, S_from, P_from, T if (CS%neutral_pos_method==1) then pos = interpolate_for_nondim_position( dRhoTop, P_top, dRhoBot, P_bot ) - ! For the 'Linear' case of finding the neutral position, the fromerence pressure to use is the average + ! For the 'Linear' case of finding the neutral position, the reference pressure to use is the average ! of the midpoint of the layer being searched and the interface being searched from elseif (CS%neutral_pos_method == 2) then pos = find_neutral_pos_linear( CS, pos_last, T_from, S_from, dRdT_from, dRdS_from, & @@ -1561,35 +1566,35 @@ function find_neutral_pos_linear( CS, z0, T_ref, S_ref, dRdT_ref, dRdS_ref, & type(neutral_diffusion_CS),intent(in) :: CS !< Control structure with parameters for this module real, intent(in) :: z0 !< Lower bound of position, also serves as the !! initial guess [nondim] - real, intent(in) :: T_ref !< Temperature at the searched from interface [degC] - real, intent(in) :: S_ref !< Salinity at the searched from interface [ppt] + real, intent(in) :: T_ref !< Temperature at the searched from interface [C ~> degC] + real, intent(in) :: S_ref !< Salinity at the searched from interface [S ~> ppt] real, intent(in) :: dRdT_ref !< dRho/dT at the searched from interface - !! [R degC-1 ~> kg m-3 degC-1] + !! [R C-1 ~> kg m-3 degC-1] real, intent(in) :: dRdS_ref !< dRho/dS at the searched from interface - !! [R ppt-1 ~> kg m-3 ppt-1] + !! [R S-1 ~> kg m-3 ppt-1] real, intent(in) :: dRdT_top !< dRho/dT at top of layer being searched - !! [R degC-1 ~> kg m-3 degC-1] + !! [R C-1 ~> kg m-3 degC-1] real, intent(in) :: dRdS_top !< dRho/dS at top of layer being searched - !! [R ppt-1 ~> kg m-3 ppt-1] + !! [R S-1 ~> kg m-3 ppt-1] real, intent(in) :: dRdT_bot !< dRho/dT at bottom of layer being searched - !! [R degC-1 ~> kg m-3 degC-1] + !! [R C-1 ~> kg m-3 degC-1] real, intent(in) :: dRdS_bot !< dRho/dS at bottom of layer being searched - !! [R ppt-1 ~> kg m-3 ppt-1] + !! [R S-1 ~> kg m-3 ppt-1] real, dimension(:), intent(in) :: ppoly_T !< Coefficients of the polynomial reconstruction of T within - !! the layer to be searched [degC]. + !! the layer to be searched [C ~> degC]. real, dimension(:), intent(in) :: ppoly_S !< Coefficients of the polynomial reconstruction of S within - !! the layer to be searched [ppt]. + !! the layer to be searched [S ~> ppt]. real :: z !< Position where drho = 0 [nondim] ! Local variables real :: dRdT_diff ! Difference in the partial derivative of density with temperature across the - ! layer [R degC-1 ~> kg m-3 degC-1] + ! layer [R C-1 ~> kg m-3 degC-1] real :: dRdS_diff ! Difference in the partial derivative of density with salinity across the - ! layer [R ppt-1 ~> kg m-3 ppt-1] - real :: drho, drho_dz ! Density anomaly and its derivative with fracitonal position [R ~> kg m-3] - real :: dRdT_z ! Partial derivative of density with temperature at a point [R degC-1 ~> kg m-3 degC-1] - real :: dRdS_z ! Partial derivative of density with salinity at a point [R ppt-1 ~> kg m-3 ppt-1] - real :: T_z, dT_dz ! Temperature at a point and its derivative with fractional position [degC] - real :: S_z, dS_dz ! Salinity at a point and its derivative with fractional position [ppt] + ! layer [R S-1 ~> kg m-3 ppt-1] + real :: drho, drho_dz ! Density anomaly and its derivative with fractional position [R ~> kg m-3] + real :: dRdT_z ! Partial derivative of density with temperature at a point [R C-1 ~> kg m-3 degC-1] + real :: dRdS_z ! Partial derivative of density with salinity at a point [R S-1 ~> kg m-3 ppt-1] + real :: T_z, dT_dz ! Temperature at a point and its derivative with fractional position [C ~> degC] + real :: S_z, dS_dz ! Salinity at a point and its derivative with fractional position [S ~> ppt] real :: drho_min, drho_max ! Bounds on density differences [R ~> kg m-3] real :: ztest, zmin, zmax ! Fractional positions in the cell [nondim] real :: a1, a2 ! Fractional weights of the top and bottom values [nondim] @@ -1680,15 +1685,15 @@ function find_neutral_pos_full( CS, z0, T_ref, S_ref, P_ref, P_top, P_bot, ppoly type(neutral_diffusion_CS),intent(in) :: CS !< Control structure with parameters for this module real, intent(in) :: z0 !< Lower bound of position, also serves as the !! initial guess [nondim] - real, intent(in) :: T_ref !< Temperature at the searched from interface [degC] - real, intent(in) :: S_ref !< Salinity at the searched from interface [ppt] + real, intent(in) :: T_ref !< Temperature at the searched from interface [C ~> degC] + real, intent(in) :: S_ref !< Salinity at the searched from interface [S ~> ppt] real, intent(in) :: P_ref !< Pressure at the searched from interface [R L2 T-2 ~> Pa] real, intent(in) :: P_top !< Pressure at top of layer being searched [R L2 T-2 ~> Pa] real, intent(in) :: P_bot !< Pressure at bottom of layer being searched [R L2 T-2 ~> Pa] real, dimension(:), intent(in) :: ppoly_T !< Coefficients of the polynomial reconstruction of T within - !! the layer to be searched [degC] + !! the layer to be searched [C ~> degC] real, dimension(:), intent(in) :: ppoly_S !< Coefficients of the polynomial reconstruction of T within - !! the layer to be searched [ppt] + !! the layer to be searched [S ~> ppt] real :: z !< Position where drho = 0 [nondim] ! Local variables integer :: iter @@ -1696,8 +1701,8 @@ function find_neutral_pos_full( CS, z0, T_ref, S_ref, P_ref, P_top, P_bot, ppoly real :: drho_a, drho_b, drho_c ! Density differences [R ~> kg m-3] real :: a, b, c ! Fractional positions [nondim] - real :: Ta, Tb, Tc ! Temperatures [degC] - real :: Sa, Sb, Sc ! Salinities [ppt] + real :: Ta, Tb, Tc ! Temperatures [C ~> degC] + real :: Sa, Sb, Sc ! Salinities [S ~> ppt] real :: Pa, Pb, Pc ! Pressures [R L2 T-2 ~> Pa] integer :: side @@ -1772,22 +1777,22 @@ end function find_neutral_pos_full subroutine calc_delta_rho_and_derivs(CS, T1, S1, p1_in, T2, S2, p2_in, drho, & drdt1_out, drds1_out, drdt2_out, drds2_out ) type(neutral_diffusion_CS) :: CS !< Neutral diffusion control structure - real, intent(in ) :: T1 !< Temperature at point 1 [degC] - real, intent(in ) :: S1 !< Salinity at point 1 [ppt] + real, intent(in ) :: T1 !< Temperature at point 1 [C ~> degC] + real, intent(in ) :: S1 !< Salinity at point 1 [S ~> ppt] real, intent(in ) :: p1_in !< Pressure at point 1 [R L2 T-2 ~> Pa] - real, intent(in ) :: T2 !< Temperature at point 2 [degC] - real, intent(in ) :: S2 !< Salinity at point 2 [ppt] + real, intent(in ) :: T2 !< Temperature at point 2 [C ~> degC] + real, intent(in ) :: S2 !< Salinity at point 2 [S ~> ppt] real, intent(in ) :: p2_in !< Pressure at point 2 [R L2 T-2 ~> Pa] real, intent( out) :: drho !< Difference in density between the two points [R ~> kg m-3] - real, optional, intent( out) :: dRdT1_out !< drho_dt at point 1 [R degC-1 ~> kg m-3 degC-1] - real, optional, intent( out) :: dRdS1_out !< drho_ds at point 1 [R ppt-1 ~> kg m-3 ppt-1] - real, optional, intent( out) :: dRdT2_out !< drho_dt at point 2 [R degC-1 ~> kg m-3 degC-1] - real, optional, intent( out) :: dRdS2_out !< drho_ds at point 2 [R ppt-1 ~> kg m-3 ppt-1] + real, optional, intent( out) :: dRdT1_out !< drho_dt at point 1 [R C-1 ~> kg m-3 degC-1] + real, optional, intent( out) :: dRdS1_out !< drho_ds at point 1 [R S-1 ~> kg m-3 ppt-1] + real, optional, intent( out) :: dRdT2_out !< drho_dt at point 2 [R C-1 ~> kg m-3 degC-1] + real, optional, intent( out) :: dRdS2_out !< drho_ds at point 2 [R S-1 ~> kg m-3 ppt-1] ! Local variables real :: rho1, rho2 ! Densities [R ~> kg m-3] real :: p1, p2, pmid ! Pressures [R L2 T-2 ~> Pa] - real :: drdt1, drdt2 ! Partial derivatives of density with temperature [R degC-1 ~> kg m-3 degC-1] - real :: drds1, drds2 ! Partial derivatives of density with salinity [R ppt-1 ~> kg m-3 ppt-1] + real :: drdt1, drdt2 ! Partial derivatives of density with temperature [R C-1 ~> kg m-3 degC-1] + real :: drds1, drds2 ! Partial derivatives of density with salinity [R S-1 ~> kg m-3 ppt-1] ! Use the same reference pressure or the in-situ pressure if (CS%ref_pres > 0.) then @@ -1801,10 +1806,10 @@ subroutine calc_delta_rho_and_derivs(CS, T1, S1, p1_in, T2, S2, p2_in, drho, & ! Use the full linear equation of state to calculate the difference in density (expensive!) if (TRIM(CS%delta_rho_form) == 'full') then pmid = 0.5 * (p1 + p2) - call calculate_density( T1, S1, pmid, rho1, CS%EOS) - call calculate_density( T2, S2, pmid, rho2, CS%EOS) + call calculate_density(T1, S1, pmid, rho1, CS%EOS) + call calculate_density(T2, S2, pmid, rho2, CS%EOS) drho = rho1 - rho2 - ! Use the density derivatives at the average of pressures and the differentces int temperature + ! Use the density derivatives at the average of pressures and the differences in temperature elseif (TRIM(CS%delta_rho_form) == 'mid_pressure') then pmid = 0.5 * (p1 + p2) if (CS%ref_pres>=0) pmid = CS%ref_pres @@ -1832,16 +1837,16 @@ end subroutine calc_delta_rho_and_derivs !! (\gamma^{-1}_1 + \gamma^{-1}_2)*(P_1-P_2) \right] \f$ function delta_rho_from_derivs( T1, S1, P1, dRdT1, dRdS1, & T2, S2, P2, dRdT2, dRdS2 ) result (drho) - real :: T1 !< Temperature at point 1 [degC] - real :: S1 !< Salinity at point 1 [ppt] + real :: T1 !< Temperature at point 1 [C ~> degC] + real :: S1 !< Salinity at point 1 [S ~> ppt] real :: P1 !< Pressure at point 1 [R L2 T-2 ~> Pa] - real :: dRdT1 !< The partial derivative of density with temperature at point 1 [R degC-1 ~> kg m-3 degC-1] - real :: dRdS1 !< The partial derivative of density with salinity at point 1 [R ppt-1 ~> kg m-3 ppt-1] - real :: T2 !< Temperature at point 2 [degC] - real :: S2 !< Salinity at point 2 [ppt] + real :: dRdT1 !< The partial derivative of density with temperature at point 1 [R C-1 ~> kg m-3 degC-1] + real :: dRdS1 !< The partial derivative of density with salinity at point 1 [R S-1 ~> kg m-3 ppt-1] + real :: T2 !< Temperature at point 2 [C ~> degC] + real :: S2 !< Salinity at point 2 [S ~> ppt] real :: P2 !< Pressure at point 2 [R L2 T-2 ~> Pa] - real :: dRdT2 !< The partial derivative of density with temperature at point 2 [R degC-1 ~> kg m-3 degC-1] - real :: dRdS2 !< The partial derivative of density with salinity at point 2 [R ppt-1 ~> kg m-3 ppt-1] + real :: dRdT2 !< The partial derivative of density with temperature at point 2 [R C-1 ~> kg m-3 degC-1] + real :: dRdS2 !< The partial derivative of density with salinity at point 2 [R S-1 ~> kg m-3 ppt-1] ! Local variables real :: drho ! The density difference [R ~> kg m-3] @@ -2015,10 +2020,10 @@ subroutine neutral_surface_flux(nk, nsurf, deg, hl, hr, Tl, Tr, PiL, PiR, KoL, K end subroutine neutral_surface_flux -!> Evaluate various parts of the reconstructions to calculate gradient-based flux limter +!> Evaluate various parts of the reconstructions to calculate gradient-based flux limiter subroutine neutral_surface_T_eval(nk, ns, k_sub, Ks, Ps, T_mean, T_int, deg, iMethod, T_poly, & T_top, T_bot, T_sub, T_top_int, T_bot_int, T_layer) - integer, intent(in ) :: nk !< Number of cell everages + integer, intent(in ) :: nk !< Number of cell averages integer, intent(in ) :: ns !< Number of neutral surfaces integer, intent(in ) :: k_sub !< Index of current neutral layer integer, dimension(ns), intent(in ) :: Ks !< List of the layers associated with each neutral surface @@ -2033,7 +2038,7 @@ subroutine neutral_surface_T_eval(nk, ns, k_sub, Ks, Ps, T_mean, T_int, deg, iMe real, intent( out) :: T_sub !< Average of the tracer value over the sublayer real, intent( out) :: T_top_int !< Tracer value at top interface of neutral layer real, intent( out) :: T_bot_int !< Tracer value at bottom interface of neutral layer - real, intent( out) :: T_layer !< Cell-average that the the reconstruction belongs to + real, intent( out) :: T_layer !< Cell-average that the reconstruction belongs to integer :: kl, ks_top, ks_bot @@ -2376,8 +2381,8 @@ logical function ndiff_unit_tests_discontinuous(verbose) real, dimension(ns) :: PoL, PoR real, dimension(ns-1) :: hEff type(neutral_diffusion_CS) :: CS !< Neutral diffusion control structure - real, dimension(nk,2) :: ppoly_T_l, ppoly_T_r ! Linear reconstruction for T - real, dimension(nk,2) :: ppoly_S_l, ppoly_S_r ! Linear reconstruction for S + real, dimension(nk,2) :: ppoly_T_l, ppoly_T_r ! Linear reconstruction for T [degC] + real, dimension(nk,2) :: ppoly_S_l, ppoly_S_r ! Linear reconstruction for S [ppt] logical, dimension(nk) :: stable_l, stable_r integer :: k logical :: v diff --git a/src/tracer/MOM_offline_aux.F90 b/src/tracer/MOM_offline_aux.F90 index c0e10c2413..0a56925516 100644 --- a/src/tracer/MOM_offline_aux.F90 +++ b/src/tracer/MOM_offline_aux.F90 @@ -637,9 +637,9 @@ subroutine update_offline_from_files(G, GV, US, nk_input, mean_file, sum_file, s real, dimension(SZI_(G),SZJB_(G),SZK_(GV)), & intent(inout) :: vhtr !< Meridional mass fluxes [H L2 ~> m3 or kg] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(inout) :: temp_mean !< Averaged temperature [degC] + intent(inout) :: temp_mean !< Averaged temperature [C ~> degC] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(inout) :: salt_mean !< Averaged salinity [ppt] + intent(inout) :: salt_mean !< Averaged salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G)), & intent(inout) :: mld !< Averaged mixed layer depth [Z ~> m] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), & @@ -682,9 +682,9 @@ subroutine update_offline_from_files(G, GV, US, nk_input, mean_file, sum_file, s call MOM_read_data(snap_file, 'h_end', h_end(:,:,1:nk_input), G%Domain, & timelevel=ridx_snap, position=CENTER, scale=convert_to_H) call MOM_read_data(mean_file, 'temp', temp_mean(:,:,1:nk_input), G%Domain, & - timelevel=ridx_sum,position=CENTER) + timelevel=ridx_sum, position=CENTER, scale=US%degC_to_C) call MOM_read_data(mean_file, 'salt', salt_mean(:,:,1:nk_input), G%Domain, & - timelevel=ridx_sum,position=CENTER) + timelevel=ridx_sum, position=CENTER, scale=US%ppt_to_S) ! Fill temperature and salinity downward from the deepest input data. do k=nk_input+1,nz ; do j=js,je ; do i=is,ie @@ -777,10 +777,10 @@ subroutine update_offline_from_arrays(G, GV, nk_input, ridx_sum, mean_file, sum_ real, dimension(:,:,:,:), allocatable, intent(inout) :: vhtr_all !< Meridional mass fluxes [H L2 ~> m3 or kg] real, dimension(:,:,:,:), allocatable, intent(inout) :: hend_all !< End of timestep layer thickness !! [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: temp !< Temperature array - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: salt !< Salinity array - real, dimension(:,:,:,:), allocatable, intent(inout) :: temp_all !< Temperature array - real, dimension(:,:,:,:), allocatable, intent(inout) :: salt_all !< Salinity array + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: temp !< Temperature array [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: salt !< Salinity array [ppt ~> S] + real, dimension(:,:,:,:), allocatable, intent(inout) :: temp_all !< Temperature array [C ~> degC] + real, dimension(:,:,:,:), allocatable, intent(inout) :: salt_all !< Salinity array [ppt ~> S] integer :: i, j, k, is, ie, js, je, nz real, parameter :: fill_value = 0. diff --git a/src/tracer/MOM_offline_main.F90 b/src/tracer/MOM_offline_main.F90 index 60267aa597..cd1572a05f 100644 --- a/src/tracer/MOM_offline_main.F90 +++ b/src/tracer/MOM_offline_main.F90 @@ -177,8 +177,8 @@ module MOM_offline_main real, allocatable, dimension(:,:,:,:) :: uhtr_all !< Entire field of zonal transport [H L2 ~> m3 or kg] real, allocatable, dimension(:,:,:,:) :: vhtr_all !< Entire field of meridional transport [H L2 ~> m3 or kg] real, allocatable, dimension(:,:,:,:) :: hend_all !< Entire field of layer thicknesses [H ~> m or kg m-2] - real, allocatable, dimension(:,:,:,:) :: temp_all !< Entire field of temperatures [degC] - real, allocatable, dimension(:,:,:,:) :: salt_all !< Entire field of salinities [ppt] + real, allocatable, dimension(:,:,:,:) :: temp_all !< Entire field of temperatures [C ~> degC] + real, allocatable, dimension(:,:,:,:) :: salt_all !< Entire field of salinities [S ~> ppt] end type offline_transport_CS @@ -1015,8 +1015,8 @@ subroutine update_offline_fields(CS, G, GV, US, h, fluxes, do_ale) call uvchksum("[uv]htr before update_offline_fields", CS%uhtr, CS%vhtr, G%HI, & scale=US%L_to_m**2*GV%H_to_kg_m2) call hchksum(CS%h_end, "h_end before update_offline_fields", G%HI, scale=GV%H_to_m) - call hchksum(CS%tv%T, "Temp before update_offline_fields", G%HI) - call hchksum(CS%tv%S, "Salt before update_offline_fields", G%HI) + call hchksum(CS%tv%T, "Temp before update_offline_fields", G%HI, scale=US%C_to_degC) + call hchksum(CS%tv%S, "Salt before update_offline_fields", G%HI, scale=US%S_to_ppt) endif ! Store a copy of the layer thicknesses before ALE regrid/remap @@ -1036,8 +1036,8 @@ subroutine update_offline_fields(CS, G, GV, US, h, fluxes, do_ale) if (CS%debug) then call uvchksum("[uv]h after update offline from files and arrays", CS%uhtr, CS%vhtr, G%HI, & scale=US%L_to_m**2*GV%H_to_kg_m2) - call hchksum(CS%tv%T, "Temp after update offline from files and arrays", G%HI) - call hchksum(CS%tv%S, "Salt after update offline from files and arrays", G%HI) + call hchksum(CS%tv%T, "Temp after update offline from files and arrays", G%HI, scale=US%C_to_degC) + call hchksum(CS%tv%S, "Salt after update offline from files and arrays", G%HI, scale=US%S_to_ppt) endif ! If using an ALE-dependent vertical coordinate, fields will need to be remapped @@ -1099,8 +1099,8 @@ subroutine update_offline_fields(CS, G, GV, US, h, fluxes, do_ale) call uvchksum("[uv]htr after update_offline_fields", CS%uhtr, CS%vhtr, G%HI, & scale=US%L_to_m**2*GV%H_to_kg_m2) call hchksum(CS%h_end, "h_end after update_offline_fields", G%HI, scale=GV%H_to_m) - call hchksum(CS%tv%T, "Temp after update_offline_fields", G%HI) - call hchksum(CS%tv%S, "Salt after update_offline_fields", G%HI) + call hchksum(CS%tv%T, "Temp after update_offline_fields", G%HI, scale=US%C_to_degC) + call hchksum(CS%tv%S, "Salt after update_offline_fields", G%HI, scale=US%S_to_ppt) endif call callTree_leave("update_offline_fields") @@ -1170,9 +1170,11 @@ subroutine register_diags_offline_transport(Time, diag, CS, GV, US) 'Meridional mass transport regridded/remapped onto offline grid', & 'kg', conversion=US%L_to_m**2*GV%H_to_kg_m2) CS%id_temp_regrid = register_diag_field('ocean_model', 'temp_regrid', diag%axesTL, Time, & - 'Temperature regridded/remapped onto offline grid','C') + 'Temperature regridded/remapped onto offline grid',& + 'C', conversion=US%C_to_degC) CS%id_salt_regrid = register_diag_field('ocean_model', 'salt_regrid', diag%axesTL, Time, & - 'Salinity regridded/remapped onto offline grid','g kg-1') + 'Salinity regridded/remapped onto offline grid', & + 'g kg-1', conversion=US%S_to_ppt) CS%id_h_regrid = register_diag_field('ocean_model', 'h_regrid', diag%axesTL, Time, & 'Layer thicknesses regridded/remapped onto offline grid', & 'm', conversion=GV%H_to_m) @@ -1498,9 +1500,9 @@ subroutine read_all_input(CS, G, GV, US) call MOM_read_data(CS%snap_file,'h_end', CS%hend_all(:,:,1:CS%nk_input,t), G%Domain, & timelevel=t, position=CENTER, scale=GV%kg_m2_to_H) call MOM_read_data(CS%mean_file,'temp', CS%temp_all(:,:,1:CS%nk_input,t), G%Domain, & - timelevel=t, position=CENTER) + timelevel=t, position=CENTER, scale=US%degC_to_C) call MOM_read_data(CS%mean_file,'salt', CS%salt_all(:,:,1:CS%nk_input,t), G%Domain, & - timelevel=t, position=CENTER) + timelevel=t, position=CENTER, scale=US%ppt_to_S) enddo endif diff --git a/src/tracer/MOM_tracer_Z_init.F90 b/src/tracer/MOM_tracer_Z_init.F90 index 7a2c64855f..85a858b8df 100644 --- a/src/tracer/MOM_tracer_Z_init.F90 +++ b/src/tracer/MOM_tracer_Z_init.F90 @@ -42,7 +42,7 @@ function tracer_Z_init(tr, h, filename, tr_name, G, GV, US, missing_val, land_va real, optional, intent(in) :: land_val !< A value to use to fill in land points ! This include declares and sets the variable "version". -#include "version_variable.h" +# include "version_variable.h" real, allocatable, dimension(:,:,:) :: & tr_in ! The z-space array of tracer concentrations that is read in. @@ -272,37 +272,43 @@ end function tracer_Z_init !> Layer model routine for remapping tracers from pseudo-z coordinates into layers defined !! by target interface positions. subroutine tracer_z_init_array(tr_in, z_edges, nk_data, e, land_fill, G, nlay, nlevs, & - eps_z, tr) + eps_z, tr, scale) type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure integer, intent(in) :: nk_data !< The number of levels in the input data real, dimension(SZI_(G),SZJ_(G),nk_data), & - intent(in) :: tr_in !< The z-space array of tracer concentrations that is read in. + intent(in) :: tr_in !< The z-space array of tracer concentrations + !! that is read in [A] real, dimension(nk_data+1), intent(in) :: z_edges !< The depths of the cell edges in the input z* data - !! [Z ~> m or m] - integer, intent(in) :: nlay !< The number of vertical layers in the target grid + !! [Z ~> m or m] + integer, intent(in) :: nlay !< The number of vertical layers in the target grid real, dimension(SZI_(G),SZJ_(G),nlay+1), & - intent(in) :: e !< The depths of the target layer interfaces [Z ~> m or m] - real, intent(in) :: land_fill !< fill in data over land (1) + intent(in) :: e !< The depths of the target layer interfaces [Z ~> m] or [m] + real, intent(in) :: land_fill !< fill in data over land [B] integer, dimension(SZI_(G),SZJ_(G)), & intent(in) :: nlevs !< The number of input levels with valid data real, intent(in) :: eps_z !< A negligibly thin layer thickness [Z ~> m]. real, dimension(SZI_(G),SZJ_(G),nlay), & - intent(out) :: tr !< tracers in layer space + intent(out) :: tr !< tracers in model space [B] + real, optional, intent(in) :: scale !< A factor by which to scale the output tracers from the + !! input tracers [B A-1 ~> 1] ! Local variables - real, dimension(nk_data) :: tr_1d !< a copy of the input tracer concentrations in a column. - real, dimension(nlay+1) :: e_1d ! A 1-d column of intreface heights, in the same units as e. + real :: tr_1d(nk_data) ! A copy of the input tracer concentrations in a column [B] + real :: e_1d(nlay+1) ! A 1-d column of interface heights, in the same units as e [Z ~> m] or [m] + real :: sl_tr ! The tracer concentration slope times the layer thickness, in tracer units [B] + real :: wt(nk_data) ! The fractional weight for each layer in the range between z1 and z2 [nondim] + real :: z1(nk_data) ! z1 and z2 are the fractional depths of the top and bottom + real :: z2(nk_data) ! limits of the part of a z-cell that contributes to a layer, relative + ! to the cell center and normalized by the cell thickness [nondim]. + ! Note that -1/2 <= z1 <= z2 <= 1/2. + real :: scale_fac ! A factor by which to scale the output tracers from the input tracers [B A-1 ~> 1] integer :: k_top, k_bot, k_bot_prev, kstart - real :: sl_tr ! The tracer concentration slope times the layer thickness, in tracer units. - real, dimension(nk_data) :: wt !< The fractional weight for each layer in the range between z1 and z2 - real, dimension(nk_data) :: z1, z2 ! z1 and z2 are the fractional depths of the top and bottom - ! limits of the part of a z-cell that contributes to a layer, relative - ! to the cell center and normalized by the cell thickness [nondim]. - ! Note that -1/2 <= z1 <= z2 <= 1/2. integer :: i, j, k, kz, is, ie, js, je is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec + scale_fac = 1.0 ; if (present(scale)) then ; scale_fac = scale ; endif + do j=js,je i_loop: do i=is,ie if (nlevs(i,j) == 0 .or. G%mask2dT(i,j) == 0.) then @@ -311,7 +317,7 @@ subroutine tracer_z_init_array(tr_in, z_edges, nk_data, e, land_fill, G, nlay, n endif do k=1,nk_data - tr_1d(k) = tr_in(i,j,k) + tr_1d(k) = scale_fac*tr_in(i,j,k) enddo do k=1,nlay+1 @@ -550,19 +556,18 @@ end function find_limited_slope !> This subroutine determines the potential temperature and salinity that !! is consistent with the target density using provided initial guess -subroutine determine_temperature(temp, salt, R_tgt, p_ref, niter, land_fill, h, k_start, G, GV, US, & +subroutine determine_temperature(temp, salt, R_tgt, p_ref, niter, h, k_start, G, GV, US, & EOS, h_massless) 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(inout) :: temp !< potential temperature [degC] + intent(inout) :: temp !< potential temperature [C ~> degC] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(inout) :: salt !< salinity [ppt] + intent(inout) :: salt !< salinity [S ~> ppt] real, dimension(SZK_(GV)), intent(in) :: R_tgt !< desired potential density [R ~> kg m-3]. real, intent(in) :: p_ref !< reference pressure [R L2 T-2 ~> Pa]. integer, intent(in) :: niter !< maximum number of iterations integer, intent(in) :: k_start !< starting index (i.e. below the buffer layer) - real, intent(in) :: land_fill !< land fill value real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: h !< layer thickness, used only to avoid working on !! massless layers [H ~> m or kg m-2] @@ -571,36 +576,48 @@ subroutine determine_temperature(temp, salt, R_tgt, p_ref, niter, land_fill, h, real, optional, intent(in) :: h_massless !< A threshold below which a layer is !! determined to be massless [H ~> m or kg m-2] - real, parameter :: T_max = 31.0, T_min = -2.0 ! Local variables (All of which need documentation!) real, dimension(SZI_(G),SZK_(GV)) :: & - T, S, dT, dS, & - rho, & ! Layer densities [R ~> kg m-3] - hin, & ! Input layer thicknesses [H ~> m or kg m-2] - drho_dT, & ! Partial derivative of density with temperature [R degC-1 ~> kg m-3 degC-1] - drho_dS ! Partial derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1] + T, & ! A 2-d working copy of the layer temperatures [C ~> degC] + S, & ! A 2-d working copy of the layer salinities [S ~> ppt] + dT, & ! An estimated change in temperature before bounding [C ~> degC] + dS, & ! An estimated change in salinity before bounding [S ~> ppt] + rho, & ! Layer densities with the current estimate of temperature and salinity [R ~> kg m-3] + hin, & ! A 2D copy of the layer thicknesses [H ~> m or kg m-2] + drho_dT, & ! Partial derivative of density with temperature [R C-1 ~> kg m-3 degC-1] + drho_dS ! Partial derivative of density with salinity [R S-1 ~> kg m-3 ppt-1] real, dimension(SZI_(G)) :: press ! Reference pressures [R L2 T-2 ~> Pa] - real :: dT_dS_gauge ! The relative penalizing of temperature to salinity changes when - ! minimizing property changes while correcting density [degC ppt-1]. - real :: I_denom ! The inverse of the magnitude squared of the density gradient in - ! T-S space streched with dT_dS_gauge [ppt2 R-2 ~> ppt2 m6 kg-2] + real :: dT_dS_gauge ! The relative penalizing of temperature to salinity changes when + ! minimizing property changes while correcting density [C S-1 ~> degC ppt-1]. + real :: I_denom ! The inverse of the magnitude squared of the density gradient in + ! T-S space when stretched with dT_dS_gauge [S2 R-2 ~> ppt2 m6 kg-2] + real :: T_min, T_max ! The minimum and maximum temperatures [C ~> degC] + real :: S_min, S_max ! Minimum and maximum salinities [S ~> ppt] + real :: tol_T ! The tolerance for temperature matches [C ~> degC] + real :: tol_S ! The tolerance for salinity matches [S ~> ppt] + real :: tol_rho ! The tolerance for density matches [R ~> kg m-3] + real :: max_t_adj ! The largest permitted temperature changes with each iteration + ! when old_fit is true [C ~> degC] + real :: max_s_adj ! The largest permitted salinity changes with each iteration + ! when old_fit is true [S ~> ppt] logical :: adjust_salt, old_fit - real :: S_min, S_max - real :: tol_T ! The tolerance for temperature matches [degC] - real :: tol_S ! The tolerance for salinity matches [ppt] - real :: tol_rho ! The tolerance for density matches [R ~> kg m-3] - real :: max_t_adj, max_s_adj integer, dimension(2) :: EOSdom ! The i-computational domain for the equation of state integer :: i, j, k, is, ie, js, je, nz, itt is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke ! These hard coded parameters need to be set properly. - S_min = 0.5 ; S_max = 65.0 - max_t_adj = 1.0 ; max_s_adj = 0.5 - tol_T=1.e-4 ; tol_S=1.e-4 ; tol_rho = 1.e-4*US%kg_m3_to_R + S_min = 0.5*US%ppt_to_S ; S_max = 65.0*US%ppt_to_S + T_max = 31.0*US%degC_to_C ; T_min = -2.0*US%degC_to_C + max_t_adj = 1.0*US%degC_to_C + max_s_adj = 0.5*US%ppt_to_S + tol_T = 1.0e-4*US%degC_to_C + tol_S = 1.0e-4*US%ppt_to_S + tol_rho = 1.0e-4*US%kg_m3_to_R old_fit = .true. ! reproduces siena behavior + dT_dS_gauge = 10.0*US%degC_to_C*US%S_to_ppt ! 10 degC is weighted equivalently to 1 ppt. + ! ### The whole determine_temperature subroutine needs to be reexamined, both the algorithms ! and the extensive use of hard-coded dimensional parameters. @@ -630,7 +647,6 @@ subroutine determine_temperature(temp, salt, R_tgt, p_ref, niter, land_fill, h, dT(i,k) = max(min((R_tgt(k)-rho(i,k)) / drho_dT(i,k), max_t_adj), -max_t_adj) T(i,k) = max(min(T(i,k)+dT(i,k), T_max), T_min) else - dT_dS_gauge = 10.0 ! 10 degC is weighted equivalently to 1 ppt. I_denom = 1.0 / (drho_dS(i,k)**2 + dT_dS_gauge**2*drho_dT(i,k)**2) dS(i,k) = (R_tgt(k)-rho(i,k)) * drho_dS(i,k) * I_denom dT(i,k) = (R_tgt(k)-rho(i,k)) * dT_dS_gauge**2*drho_dT(i,k) * I_denom diff --git a/src/tracer/MOM_tracer_flow_control.F90 b/src/tracer/MOM_tracer_flow_control.F90 index 94e4b669ea..57a912f1db 100644 --- a/src/tracer/MOM_tracer_flow_control.F90 +++ b/src/tracer/MOM_tracer_flow_control.F90 @@ -344,7 +344,7 @@ subroutine tracer_flow_control_init(restart, day, G, GV, US, h, param_file, diag call initialize_MOM_generic_tracer(restart, day, G, GV, US, h, param_file, diag, OBC, & CS%MOM_generic_tracer_CSp, sponge_CSp, ALE_sponge_CSp) if (CS%use_pseudo_salt_tracer) & - call initialize_pseudo_salt_tracer(restart, day, G, GV, h, diag, OBC, CS%pseudo_salt_tracer_CSp, & + call initialize_pseudo_salt_tracer(restart, day, G, GV, US, h, diag, OBC, CS%pseudo_salt_tracer_CSp, & sponge_CSp, tv) if (CS%use_boundary_impulse_tracer) & call initialize_boundary_impulse_tracer(restart, day, G, GV, US, h, diag, OBC, CS%boundary_impulse_tracer_CSp, & diff --git a/src/tracer/MOM_tracer_hor_diff.F90 b/src/tracer/MOM_tracer_hor_diff.F90 index 24252dfedc..22e41c2c1d 100644 --- a/src/tracer/MOM_tracer_hor_diff.F90 +++ b/src/tracer/MOM_tracer_hor_diff.F90 @@ -711,7 +711,7 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, & ! Determine which layers the mixed- and buffer-layers map into... !$OMP parallel do default(shared) do k=1,nkmb ; do j=js-2,je+2 - call calculate_density(tv%T(:,j,k),tv%S(:,j,k), p_ref_cv, rho_coord(:,j,k), & + call calculate_density(tv%T(:,j,k), tv%S(:,j,k), p_ref_cv, rho_coord(:,j,k), & tv%eqn_of_state, EOSdom) enddo ; enddo diff --git a/src/tracer/MOM_tracer_registry.F90 b/src/tracer/MOM_tracer_registry.F90 index 821ac6a3cd..62126801a9 100644 --- a/src/tracer/MOM_tracer_registry.F90 +++ b/src/tracer/MOM_tracer_registry.F90 @@ -37,8 +37,8 @@ module MOM_tracer_registry !> The tracer type type, public :: tracer_type - real, dimension(:,:,:), pointer :: t => NULL() !< tracer concentration array [conc] -! real :: OBC_inflow_conc= 0.0 !< tracer concentration for generic inflows [conc] + real, dimension(:,:,:), pointer :: t => NULL() !< tracer concentration array [CU ~> conc] +! real :: OBC_inflow_conc= 0.0 !< tracer concentration for generic inflows [CU ~> conc] ! real, dimension(:,:,:), pointer :: OBC_in_u => NULL() !< structured values for flow into the domain ! !! specified in OBCs through u-face of cell ! real, dimension(:,:,:), pointer :: OBC_in_v => NULL() !< structured values for flow into the domain @@ -87,10 +87,10 @@ module MOM_tracer_registry ! !! expressed as a change in concentration ! !! [conc T-1 ~> conc s-1] real, dimension(:,:,:), pointer :: t_prev => NULL() !< tracer concentration array at a previous - !! timestep used for diagnostics [conc] + !! timestep used for diagnostics [CU ~> conc] real, dimension(:,:,:), pointer :: Trxh_prev => NULL() !< layer integrated tracer concentration array !! at a previous timestep used for diagnostics - !! [conc H ~> conc m or conc kg m-2] + !! [CU ~> H ~> conc m or conc kg m-2] character(len=32) :: name !< tracer name used for diagnostics and error messages character(len=64) :: units !< Physical dimensions of the tracer concentration @@ -98,6 +98,8 @@ module MOM_tracer_registry ! type(vardesc), pointer :: vd => NULL() !< metadata describing the tracer logical :: registry_diags = .false. !< If true, use the registry to set up the !! diagnostics associated with this tracer. + real :: conc_scale = 1.0 !< A scaling factor used to convert the concentrations + !! of this tracer to its desired units. character(len=64) :: cmor_name !< CMOR name of this tracer character(len=64) :: cmor_units !< CMOR physical dimensions of the tracer character(len=240) :: cmor_longname !< CMOR long name of the tracer @@ -157,7 +159,7 @@ subroutine register_tracer(tr_ptr, Reg, param_file, HI, GV, name, longname, unit cmor_name, cmor_units, cmor_longname, tr_desc, & OBC_inflow, OBC_in_u, OBC_in_v, ad_x, ad_y, df_x, df_y, & ad_2d_x, ad_2d_y, df_2d_x, df_2d_y, advection_xy, registry_diags, & - flux_nameroot, flux_longname, flux_units, flux_scale, & + conc_scale, flux_nameroot, flux_longname, flux_units, flux_scale, & convergence_units, convergence_scale, cmor_tendprefix, diag_form, & restart_CS, mandatory) type(hor_index_type), intent(in) :: HI !< horizontal index type @@ -202,6 +204,8 @@ subroutine register_tracer(tr_ptr, Reg, param_file, HI, GV, name, longname, unit real, dimension(:,:,:), optional, pointer :: advection_xy !< convergence of lateral advective tracer fluxes logical, optional, intent(in) :: registry_diags !< If present and true, use the registry for !! the diagnostics of this tracer. + real, optional, intent(in) :: conc_scale !< A scaling factor used to convert the concentration + !! of this tracer to its desired units. character(len=*), optional, intent(in) :: flux_nameroot !< Short tracer name snippet used construct the !! names of flux diagnostics. character(len=*), optional, intent(in) :: flux_longname !< A word or phrase used construct the long @@ -267,6 +271,9 @@ subroutine register_tracer(tr_ptr, Reg, param_file, HI, GV, name, longname, unit "MOM register_tracer was called for variable "//trim(Tr%name)//& " with a locked tracer registry.") + Tr%conc_scale = 1.0 + if (present(conc_scale)) Tr%conc_scale = conc_scale + Tr%flux_nameroot = Tr%name if (present(flux_nameroot)) then if (len_trim(flux_nameroot) > 0) Tr%flux_nameroot = flux_nameroot @@ -280,7 +287,7 @@ subroutine register_tracer(tr_ptr, Reg, param_file, HI, GV, name, longname, unit Tr%flux_units = "" if (present(flux_units)) Tr%flux_units = flux_units - Tr%flux_scale = GV%H_to_MKS + Tr%flux_scale = GV%H_to_MKS*Tr%conc_scale if (present(flux_scale)) Tr%flux_scale = flux_scale Tr%conv_units = "" @@ -289,7 +296,7 @@ subroutine register_tracer(tr_ptr, Reg, param_file, HI, GV, name, longname, unit Tr%cmor_tendprefix = "" if (present(cmor_tendprefix)) Tr%cmor_tendprefix = cmor_tendprefix - Tr%conv_scale = GV%H_to_MKS + Tr%conv_scale = GV%H_to_MKS*Tr%conc_scale if (present(convergence_scale)) then Tr%conv_scale = convergence_scale elseif (present(flux_scale)) then @@ -321,7 +328,7 @@ subroutine register_tracer(tr_ptr, Reg, param_file, HI, GV, name, longname, unit mand = .true. ; if (present(mandatory)) mand = mandatory call register_restart_field(tr_ptr, Tr%name, mand, restart_CS, & - longname=Tr%longname, units=Tr%units) + longname=Tr%longname, units=Tr%units, conversion=conc_scale) endif end subroutine register_tracer @@ -400,17 +407,17 @@ subroutine register_tracer_diagnostics(Reg, h, Time, diag, G, GV, US, use_ALE) if (len_trim(cmorname) == 0) then Tr%id_tr = register_diag_field("ocean_model", trim(name), diag%axesTL, & - Time, trim(longname), trim(units)) + Time, trim(longname), trim(units), conversion=Tr%conc_scale) else Tr%id_tr = register_diag_field("ocean_model", trim(name), diag%axesTL, & - Time, trim(longname), trim(units), cmor_field_name=cmorname, & - cmor_long_name=cmor_longname, cmor_units=Tr%cmor_units, & - cmor_standard_name=cmor_long_std(cmor_longname)) + Time, trim(longname), trim(units), conversion=Tr%conc_scale, & + cmor_field_name=cmorname, cmor_long_name=cmor_longname, & + cmor_units=Tr%cmor_units, cmor_standard_name=cmor_long_std(cmor_longname)) endif Tr%id_tr_post_horzn = register_diag_field("ocean_model", & trim(name)//"_post_horzn", diag%axesTL, Time, & trim(longname)//" after horizontal transport (advection/diffusion) has occurred", & - trim(units)) + trim(units), conversion=Tr%conc_scale) if (Tr%diag_form == 1) then Tr%id_adx = register_diag_field("ocean_model", trim(shortnm)//"_adx", & diag%axesCuL, Time, trim(flux_longname)//" advective zonal flux" , & @@ -526,7 +533,8 @@ subroutine register_tracer_diagnostics(Reg, h, Time, diag, G, GV, US, use_ALE) Tr%id_tendency = register_diag_field('ocean_model', trim(shortnm)//'_tendency', & diag%axesTL, Time, & - 'Net time tendency for '//trim(lowercase(longname)), trim(units)//' s-1', conversion=US%s_to_T) + 'Net time tendency for '//trim(lowercase(longname)), & + trim(units)//' s-1', conversion=Tr%conc_scale*US%s_to_T) if (Tr%id_tendency > 0) then call safe_alloc_ptr(Tr%t_prev,isd,ied,jsd,jed,nz) @@ -584,11 +592,11 @@ subroutine register_tracer_diagnostics(Reg, h, Time, diag, G, GV, US, use_ALE) endif Tr%id_dfxy_conc = register_diag_field("ocean_model", trim(shortnm)//'_dfxy_conc_tendency', & diag%axesTL, Time, "Neutral diffusion tracer concentration tendency for "//trim(shortnm), & - trim(units)//' s-1', conversion=US%s_to_T) + trim(units)//' s-1', conversion=Tr%conc_scale*US%s_to_T) Tr%id_lbdxy_conc = register_diag_field("ocean_model", trim(shortnm)//'_lbdxy_conc_tendency', & diag%axesTL, Time, "Lateral diffusion tracer concentration tendency for "//trim(shortnm), & - trim(units)//' s-1', conversion=US%s_to_T) + trim(units)//' s-1', conversion=Tr%conc_scale*US%s_to_T) var_lname = "Net time tendency for "//lowercase(flux_longname) if (len_trim(Tr%cmor_tendprefix) == 0) then @@ -625,7 +633,7 @@ subroutine register_tracer_diagnostics(Reg, h, Time, diag, G, GV, US, use_ALE) var_lname = "Vertical remapping tracer concentration tendency for "//trim(Reg%Tr(m)%name) Tr%id_remap_conc= register_diag_field('ocean_model', & trim(Tr%flux_nameroot)//'_tendency_vert_remap', diag%axesTL, Time, var_lname, & - trim(units)//' s-1', conversion=US%s_to_T) + trim(units)//' s-1', conversion=Tr%conc_scale*US%s_to_T) var_lname = "Vertical remapping tracer content tendency for "//trim(Reg%Tr(m)%flux_longname) Tr%id_remap_cont = register_diag_field('ocean_model', & @@ -644,7 +652,8 @@ subroutine register_tracer_diagnostics(Reg, h, Time, diag, G, GV, US, use_ALE) unit2 = trim(units)//"2" if (index(units(1:len_trim(units))," ") > 0) unit2 = "("//trim(units)//")2" Tr%id_tr_vardec = register_diag_field('ocean_model', trim(shortnm)//"_vardec", diag%axesTL, & - Time, "ALE variance decay for "//lowercase(longname), trim(unit2)//" s-1", conversion=US%s_to_T) + Time, "ALE variance decay for "//lowercase(longname), & + trim(unit2)//" s-1", conversion=Tr%conc_scale**2*US%s_to_T) if (Tr%id_tr_vardec > 0) then ! Set up a new tracer for this tracer squared m2 = Reg%ntr+1 @@ -811,7 +820,7 @@ subroutine MOM_tracer_chksum(mesg, Tr, ntr, G) integer :: m do m=1,ntr - call hchksum(Tr(m)%t, mesg//trim(Tr(m)%name), G%HI) + call hchksum(Tr(m)%t, mesg//trim(Tr(m)%name), G%HI, scale=Tr(m)%conc_scale) enddo end subroutine MOM_tracer_chksum @@ -836,7 +845,7 @@ subroutine MOM_tracer_chkinv(mesg, G, GV, h, Tr, ntr) vol_scale = GV%H_to_m*G%US%L_to_m**2 do m=1,ntr do k=1,nz ; do j=js,je ; do i=is,ie - tr_inv(i,j,k) = Tr(m)%t(i,j,k) * (vol_scale * h(i,j,k) * G%areaT(i,j)*G%mask2dT(i,j)) + tr_inv(i,j,k) = Tr(m)%conc_scale*Tr(m)%t(i,j,k) * (vol_scale * h(i,j,k) * G%areaT(i,j)*G%mask2dT(i,j)) enddo ; enddo ; enddo total_inv = reproducing_sum(tr_inv, is+(1-G%isd), ie+(1-G%isd), js+(1-G%jsd), je+(1-G%jsd)) if (is_root_pe()) write(0,'(A,1X,A5,1X,ES25.16,1X,A)') "h-point: inventory", Tr(m)%name, total_inv, mesg diff --git a/src/tracer/oil_tracer.F90 b/src/tracer/oil_tracer.F90 index 900377fe83..5592b7627a 100644 --- a/src/tracer/oil_tracer.F90 +++ b/src/tracer/oil_tracer.F90 @@ -362,7 +362,8 @@ subroutine oil_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, US if (CS%oil_decay_rate(m)>0.) then CS%tr(i,j,k,m) = G%mask2dT(i,j)*max(1. - dt*CS%oil_decay_rate(m),0.)*CS%tr(i,j,k,m) ! Safest elseif (CS%oil_decay_rate(m)<0.) then - decay_timescale = (12.*(3.0**(-(tv%T(i,j,k)-20.)/10.))) * (86400.*US%s_to_T) ! Timescale [s ~> T] + decay_timescale = (12.0 * (3.0**(-(tv%T(i,j,k)-20.0*US%degC_to_C)/10.0*US%degC_to_C))) * & + (86400.0*US%s_to_T) ! Timescale [s ~> T] ldecay = 1. / decay_timescale ! Rate [T-1 ~> s-1] CS%tr(i,j,k,m) = G%mask2dT(i,j)*max(1. - dt*ldecay,0.)*CS%tr(i,j,k,m) endif diff --git a/src/tracer/pseudo_salt_tracer.F90 b/src/tracer/pseudo_salt_tracer.F90 index 6c22daa150..ece4e09b65 100644 --- a/src/tracer/pseudo_salt_tracer.F90 +++ b/src/tracer/pseudo_salt_tracer.F90 @@ -107,13 +107,14 @@ function register_pseudo_salt_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS) end function register_pseudo_salt_tracer !> Initialize the pseudo-salt tracer -subroutine initialize_pseudo_salt_tracer(restart, day, G, GV, h, diag, OBC, CS, & +subroutine initialize_pseudo_salt_tracer(restart, day, G, GV, US, h, diag, OBC, CS, & sponge_CSp, tv) logical, intent(in) :: restart !< .true. if the fields have already !! been read from a restart file. type(time_type), target, intent(in) :: day !< Time of the start of the run type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2] type(diag_ctrl), target, intent(in) :: diag !< A structure that is used to regulate @@ -143,7 +144,7 @@ subroutine initialize_pseudo_salt_tracer(restart, day, G, GV, h, diag, OBC, CS, call query_vardesc(CS%tr_desc, name=name, caller="initialize_pseudo_salt_tracer") if ((.not.restart) .or. (.not.query_initialized(CS%ps, name, CS%restart_CSp))) then do k=1,nz ; do j=jsd,jed ; do i=isd,ied - CS%ps(i,j,k) = tv%S(i,j,k) + CS%ps(i,j,k) = US%S_to_ppt*tv%S(i,j,k) enddo ; enddo ; enddo endif @@ -208,7 +209,7 @@ subroutine pseudo_salt_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G if (.not.associated(CS%ps)) return if (debug) then - call hchksum(tv%S,"salt pre pseudo-salt vertdiff", G%HI) + call hchksum(tv%S,"salt pre pseudo-salt vertdiff", G%HI, scale=US%S_to_ppt) call hchksum(CS%ps,"pseudo_salt pre pseudo-salt vertdiff", G%HI) endif @@ -239,13 +240,13 @@ subroutine pseudo_salt_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G endif if (debug) then - call hchksum(tv%S, "salt post pseudo-salt vertdiff", G%HI) + call hchksum(tv%S, "salt post pseudo-salt vertdiff", G%HI, scale=US%S_to_ppt) call hchksum(CS%ps, "pseudo_salt post pseudo-salt vertdiff", G%HI) endif if (allocated(CS%diff)) then do k=1,nz ; do j=js,je ; do i=is,ie - CS%diff(i,j,k) = CS%ps(i,j,k) - tv%S(i,j,k) + CS%diff(i,j,k) = CS%ps(i,j,k) - US%S_to_ppt*tv%S(i,j,k) enddo ; enddo ; enddo if (CS%id_psd>0) call post_data(CS%id_psd, CS%diff, CS%diag) endif diff --git a/src/user/DOME2d_initialization.F90 b/src/user/DOME2d_initialization.F90 index 807dbc0e2a..054a9fe81c 100644 --- a/src/user/DOME2d_initialization.F90 +++ b/src/user/DOME2d_initialization.F90 @@ -218,12 +218,13 @@ end subroutine DOME2d_initialize_thickness !> Initialize temperature and salinity in the 2d DOME configuration -subroutine DOME2d_initialize_temperature_salinity ( T, S, h, G, GV, param_file, just_read) +subroutine DOME2d_initialize_temperature_salinity ( T, S, h, G, GV, US, param_file, just_read) type(ocean_grid_type), intent(in) :: G !< Ocean grid structure type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure. - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2] + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< Parameter file structure logical, intent(in) :: just_read !< If true, this call will !! only read parameters without changing T & S. @@ -232,8 +233,8 @@ subroutine DOME2d_initialize_temperature_salinity ( T, S, h, G, GV, param_file, real :: x integer :: index_bay_z real :: delta_S - real :: S_ref, T_ref ! Reference salinity and temperature within surface layer - real :: S_range, T_range ! Range of salinities and temperatures over the vertical + real :: S_ref, T_ref ! Reference salinity [S ~> ppt] and temperature [C ~> degC] within surface layer + real :: S_range, T_range ! Range of salinities [S ~> ppt] and temperatures [C ~> degC] over the vertical real :: xi0, xi1 character(len=40) :: verticalCoordinate real :: dome2d_width_bay, dome2d_width_bottom, dome2d_depth_bay @@ -249,13 +250,13 @@ subroutine DOME2d_initialize_temperature_salinity ( T, S, h, G, GV, param_file, call get_param(param_file, mdl, "DOME2D_SHELF_DEPTH", dome2d_depth_bay, & default=0.2, do_not_log=.true.) call get_param(param_file, mdl, "S_REF", S_ref, 'Reference salinity', & - default=35.0, units='1e-3', do_not_log=just_read) - call get_param(param_file, mdl,"T_REF",T_ref,'Reference temperature', units='degC', & - fail_if_missing=.not.just_read, do_not_log=just_read) - call get_param(param_file, mdl,"S_RANGE",S_range,'Initial salinity range', & - units='1e-3', default=2.0, do_not_log=just_read) - call get_param(param_file, mdl,"T_RANGE",T_range,'Initial temperature range', & - units='1e-3', default=0.0, do_not_log=just_read) + default=35.0, units='1e-3', scale=US%ppt_to_S, do_not_log=just_read) + call get_param(param_file, mdl, "T_REF", T_ref, 'Reference temperature', & + units='degC', scale=US%degC_to_C, fail_if_missing=.not.just_read, do_not_log=just_read) + call get_param(param_file, mdl, "S_RANGE", S_range,' Initial salinity range', & + units='1e-3', default=2.0, scale=US%ppt_to_S, do_not_log=just_read) + call get_param(param_file, mdl, "T_RANGE", T_range, 'Initial temperature range', & + units='degC', default=0.0, scale=US%degC_to_C, do_not_log=just_read) if (just_read) return ! All run-time parameters have been read, so return. @@ -272,7 +273,7 @@ subroutine DOME2d_initialize_temperature_salinity ( T, S, h, G, GV, param_file, xi0 = 0.0 do k = 1,nz xi1 = xi0 + (GV%H_to_Z * h(i,j,k)) / G%max_depth - S(i,j,k) = 34.0 + 0.5 * S_range * (xi0 + xi1) + S(i,j,k) = 34.0*US%ppt_to_S + 0.5 * S_range * (xi0 + xi1) xi0 = xi1 enddo enddo ; enddo @@ -283,12 +284,12 @@ subroutine DOME2d_initialize_temperature_salinity ( T, S, h, G, GV, param_file, xi0 = 0.0 do k = 1,nz xi1 = xi0 + (GV%H_to_Z * h(i,j,k)) / G%max_depth - S(i,j,k) = 34.0 + 0.5 * S_range * (xi0 + xi1) + S(i,j,k) = 34.0*US%ppt_to_S + 0.5 * S_range * (xi0 + xi1) xi0 = xi1 enddo x = ( G%geoLonT(i,j) - G%west_lon ) / G%len_lon if ( x <= dome2d_width_bay ) then - S(i,j,nz) = 34.0 + S_range + S(i,j,nz) = 34.0*US%ppt_to_S + S_range endif enddo ; enddo @@ -312,8 +313,8 @@ subroutine DOME2d_initialize_temperature_salinity ( T, S, h, G, GV, param_file, do j = G%jsc,G%jec ; do i = G%isc,G%iec x = ( G%geoLonT(i,j) - G%west_lon ) / G%len_lon if ( x <= dome2d_width_bay ) then - S(i,j,1:index_bay_z) = S_ref + S_range; ! Use for z coordinates - T(i,j,1:index_bay_z) = 1.0; ! Use for z coordinates + S(i,j,1:index_bay_z) = S_ref + S_range ! Use for z coordinates + T(i,j,1:index_bay_z) = 1.0*US%degC_to_C ! Use for z coordinates endif enddo ; enddo ! i and j loops endif ! Z initial conditions @@ -323,8 +324,8 @@ subroutine DOME2d_initialize_temperature_salinity ( T, S, h, G, GV, param_file, do i = G%isc,G%iec ; do j = G%jsc,G%jec x = ( G%geoLonT(i,j) - G%west_lon ) / G%len_lon if ( x <= dome2d_width_bay ) then - S(i,j,1:GV%ke) = S_ref + S_range; ! Use for sigma coordinates - T(i,j,1:GV%ke) = 1.0; ! Use for sigma coordinates + S(i,j,1:GV%ke) = S_ref + S_range ! Use for sigma coordinates + T(i,j,1:GV%ke) = 1.0*US%degC_to_C ! Use for sigma coordinates endif enddo ; enddo endif @@ -336,7 +337,7 @@ subroutine DOME2d_initialize_temperature_salinity ( T, S, h, G, GV, param_file, do i = G%isc,G%iec ; do j = G%jsc,G%jec x = ( G%geoLonT(i,j) - G%west_lon ) / G%len_lon if ( x <= dome2d_width_bay ) then - T(i,j,GV%ke) = 1.0 + T(i,j,GV%ke) = 1.0*US%degC_to_C endif enddo ; enddo endif @@ -356,15 +357,15 @@ subroutine DOME2d_initialize_sponges(G, GV, US, tv, depth_tot, param_file, use_A type(sponge_CS), pointer :: CSp !< Layer-mode sponge structure type(ALE_sponge_CS), pointer :: ACSp !< ALE-mode sponge structure ! Local variables - real :: T(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for temp [degC] - real :: S(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for salt [ppt] + real :: T(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for temp [C ~> degC] + real :: S(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for salt [S ~> ppt] real :: h(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for thickness [H ~> m or kg m-2]. real :: eta(SZI_(G),SZJ_(G),SZK_(GV)+1) ! A temporary array for interface heights [Z ~> m] real :: Idamp(SZI_(G),SZJ_(G)) ! The sponge damping rate [T-1 ~> s-1] - real :: S_ref ! Reference salinity within the surface layer [ppt] - real :: T_ref ! Reference temerature within the surface layer [degC] - real :: S_range ! Range of salinities in the vertical [ppt] - real :: T_range ! Range of temperatures in the vertical [degC] + real :: S_ref ! Reference salinity within the surface layer [S ~> ppt] + real :: T_ref ! Reference temperature within the surface layer [C ~> degC] + real :: S_range ! Range of salinities in the vertical [S ~> ppt] + real :: T_range ! Range of temperatures in the vertical [C ~> degC] real :: e0(SZK_(GV)+1) ! The resting interface heights [Z ~> m], ! usually negative because it is positive upward. real :: eta1D(SZK_(GV)+1) ! Interface height relative to the sea surface @@ -410,10 +411,10 @@ subroutine DOME2d_initialize_sponges(G, GV, US, tv, depth_tot, param_file, use_A default=0.3, do_not_log=.true.) call get_param(param_file, mdl, "DOME2D_SHELF_DEPTH", dome2d_depth_bay, & default=0.2, do_not_log=.true.) - call get_param(param_file, mdl, "S_REF", S_ref, default=35.0) - call get_param(param_file, mdl, "T_REF", T_ref) - call get_param(param_file, mdl, "S_RANGE", S_range, default=2.0) - call get_param(param_file, mdl, "T_RANGE", T_range, default=0.0) + call get_param(param_file, mdl, "S_REF", S_ref, default=35.0, scale=US%ppt_to_S) + call get_param(param_file, mdl, "T_REF", T_ref, scale=US%degC_to_C) + call get_param(param_file, mdl, "S_RANGE", S_range, default=2.0, scale=US%ppt_to_S) + call get_param(param_file, mdl, "T_RANGE", T_range, default=0.0, scale=US%degC_to_C) ! Set the sponge damping rate as a function of position @@ -466,7 +467,7 @@ subroutine DOME2d_initialize_sponges(G, GV, US, tv, depth_tot, param_file, use_A z = -depth_tot(i,j) do k = nz,1,-1 z = z + 0.5 * GV%H_to_Z * h(i,j,k) ! Position of the center of layer k - S(i,j,k) = 34.0 - 1.0 * (z / (G%max_depth)) + S(i,j,k) = 34.0*US%ppt_to_S - 1.0*US%ppt_to_S * (z / (G%max_depth)) if ( ( G%geoLonT(i,j) - G%west_lon ) / G%len_lon < dome2d_west_sponge_width ) & S(i,j,k) = S_ref + S_range z = z + 0.5 * GV%H_to_Z * h(i,j,k) ! Position of the interface k diff --git a/src/user/DOME_initialization.F90 b/src/user/DOME_initialization.F90 index 859b736380..a78ed3acc4 100644 --- a/src/user/DOME_initialization.F90 +++ b/src/user/DOME_initialization.F90 @@ -275,11 +275,11 @@ subroutine DOME_set_OBC_data(OBC, tv, G, GV, US, param_file, tr_Reg) type(tracer_registry_type), pointer :: tr_Reg !< Tracer registry. ! Local variables - real :: T0(SZK_(GV)) ! A profile of target temperatures [degC] - real :: S0(SZK_(GV)) ! A profile of target salinities [ppt] + real :: T0(SZK_(GV)) ! A profile of target temperatures [C ~> degC] + real :: S0(SZK_(GV)) ! A profile of target salinities [S ~> ppt] real :: pres(SZK_(GV)) ! An array of the reference pressure [R L2 T-2 ~> Pa]. - real :: drho_dT(SZK_(GV)) ! Derivative of density with temperature [R degC-1 ~> kg m-3 degC-1]. - real :: drho_dS(SZK_(GV)) ! Derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1]. + real :: drho_dT(SZK_(GV)) ! Derivative of density with temperature [R C-1 ~> kg m-3 degC-1]. + real :: drho_dS(SZK_(GV)) ! Derivative of density with salinity [R S-1 ~> kg m-3 ppt-1]. real :: rho_guess(SZK_(GV)) ! Potential density at T0 & S0 [R ~> kg m-3]. ! The following variables are used to set up the transport in the DOME example. real :: tr_0 ! The total integrated inflow transport [H L2 T-1 ~> m3 s-1 or kg s-1] @@ -370,13 +370,13 @@ subroutine DOME_set_OBC_data(OBC, tv, G, GV, US, param_file, tr_Reg) ! In this example, all S inflows have values of 35 psu. name = 'salt' call tracer_name_lookup(tr_Reg, tr_ptr, name) - call register_segment_tracer(tr_ptr, param_file, GV, segment, OBC_scalar=35.0) + call register_segment_tracer(tr_ptr, param_file, GV, segment, OBC_scalar=35.0*US%ppt_to_S, scale=US%ppt_to_S) endif if (associated(tv%T)) then ! In this example, the T values are set to be consistent with the layer ! target density and a salinity of 35 psu. This code is taken from ! USER_initialize_temp_sal. - pres(:) = tv%P_Ref ; S0(:) = 35.0 ; T0(1) = 25.0 + pres(:) = tv%P_Ref ; S0(:) = 35.0*US%ppt_to_S ; T0(1) = 25.0*US%degC_to_C call calculate_density(T0(1), S0(1), pres(1), rho_guess(1), tv%eqn_of_state) call calculate_density_derivs(T0, S0, pres, drho_dT, drho_dS, tv%eqn_of_state, (/1,1/) ) @@ -390,11 +390,13 @@ subroutine DOME_set_OBC_data(OBC, tv, G, GV, US, param_file, tr_Reg) ! Temperature is tracer 1 for the OBCs. allocate(segment%field(1)%buffer_src(segment%HI%isd:segment%HI%ied,segment%HI%JsdB:segment%HI%JedB,nz)) do k=1,nz ; do J=JsdB,JedB ; do i=isd,ied - segment%field(1)%buffer_src(i,j,k) = T0(k) + ! Because of the challenges in rescaling the data as it is being read in when using certain + ! modes, buffer_src keeps the data in unscaled (mks) units. They will be rescaled later. + segment%field(1)%buffer_src(i,j,k) = US%C_to_degC*T0(k) enddo ; enddo ; enddo name = 'temp' call tracer_name_lookup(tr_Reg, tr_ptr, name) - call register_segment_tracer(tr_ptr, param_file, GV, segment, OBC_array=.true.) + call register_segment_tracer(tr_ptr, param_file, GV, segment, OBC_array=.true., scale=US%degC_to_C) endif ! Set up dye tracers diff --git a/src/user/ISOMIP_initialization.F90 b/src/user/ISOMIP_initialization.F90 index a67f3b09ed..5e91eaa86a 100644 --- a/src/user/ISOMIP_initialization.F90 +++ b/src/user/ISOMIP_initialization.F90 @@ -61,7 +61,7 @@ subroutine ISOMIP_initialize_topography(D, G, param_file, max_depth, US) real :: xtil ! dummy vatiable logical :: is_2D ! If true, use 2D setup ! This include declares and sets the variable "version". -#include "version_variable.h" +# include "version_variable.h" character(len=40) :: mdl = "ISOMIP_initialize_topography" ! This subroutine's name. integer :: i, j, is, ie, js, je, isd, ied, jsd, jed is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec @@ -146,7 +146,9 @@ subroutine ISOMIP_initialize_thickness ( h, depth_tot, G, GV, US, param_file, tv real :: eta1D(SZK_(GV)+1) ! Interface height relative to the sea surface ! positive upward, in depth units [Z ~> m]. integer :: i, j, k, is, ie, js, je, nz - real :: min_thickness, s_sur, s_bot, t_sur, t_bot + real :: min_thickness ! Minimum layer thicknesses [Z ~> m] + real :: S_sur, S_bot ! Surface and bottom salinities [S ~> ppt] + real :: T_sur, T_bot ! Surface and bottom temperatures [C ~> degC] real :: rho_sur, rho_bot ! Surface and bottom densities [R ~> kg m-3] real :: rho_range ! The range of densities [R ~> kg m-3] !character(len=256) :: mesg ! The text of an error message @@ -166,21 +168,25 @@ subroutine ISOMIP_initialize_thickness ( h, depth_tot, G, GV, US, param_file, tv case ( REGRIDDING_LAYER, REGRIDDING_RHO ) ! Initial thicknesses for isopycnal coordinates call get_param(param_file, mdl, "ISOMIP_T_SUR", t_sur, & - "Temperature at the surface (interface)", units="degC", default=-1.9, do_not_log=just_read) + "Temperature at the surface (interface)", & + units="degC", default=-1.9, scale=US%degC_to_C, do_not_log=just_read) call get_param(param_file, mdl, "ISOMIP_S_SUR", s_sur, & - "Salinity at the surface (interface)", units="ppt", default=33.8, do_not_log=just_read) + "Salinity at the surface (interface)", & + units="ppt", default=33.8, scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl, "ISOMIP_T_BOT", t_bot, & - "Temperature at the bottom (interface)", units="degC", default=-1.9, do_not_log=just_read) - call get_param(param_file, mdl, "ISOMIP_S_BOT", s_bot,& - "Salinity at the bottom (interface)", units="ppt", default=34.55, do_not_log=just_read) + "Temperature at the bottom (interface)", & + units="degC", default=-1.9, scale=US%degC_to_C, do_not_log=just_read) + call get_param(param_file, mdl, "ISOMIP_S_BOT", s_bot, & + "Salinity at the bottom (interface)", & + units="ppt", default=34.55, scale=US%ppt_to_S, do_not_log=just_read) if (just_read) return ! All run-time parameters have been read, so return. ! Compute min/max density using T_SUR/S_SUR and T_BOT/S_BOT - call calculate_density(t_sur, s_sur, 0.0, rho_sur, tv%eqn_of_state) + call calculate_density(T_sur, S_sur, 0.0, rho_sur, tv%eqn_of_state) ! write(mesg,*) 'Surface density is:', rho_sur ! call MOM_mesg(mesg,5) - call calculate_density(t_bot, s_bot, 0.0, rho_bot, tv%eqn_of_state) + call calculate_density(T_bot, S_bot, 0.0, rho_bot, tv%eqn_of_state) ! write(mesg,*) 'Bottom density is:', rho_bot ! call MOM_mesg(mesg,5) rho_range = rho_bot - rho_sur @@ -248,8 +254,8 @@ subroutine ISOMIP_initialize_temperature_salinity ( T, S, h, depth_tot, G, GV, U type(ocean_grid_type), intent(in) :: G !< Ocean grid structure type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2] real, dimension(SZI_(G),SZJ_(G)), intent(in) :: depth_tot !< The nominal total bottom-to-top !! depth of the ocean [Z ~> m] @@ -261,22 +267,22 @@ subroutine ISOMIP_initialize_temperature_salinity ( T, S, h, depth_tot, G, GV, U integer :: i, j, k, is, ie, js, je, nz, itt real :: rho_sur, rho_bot ! Surface and bottom densities [R ~> kg m-3] real :: xi0, xi1 ! Heights in depth units [Z ~> m]. - real :: S_sur, S_bot ! Salinity at the surface and bottom [ppt] - real :: T_sur, T_bot ! Temperature at the bottom [degC] - real :: dT_dz ! Vertical gradient of temperature [degC Z-1 ~> degC m-1]. - real :: dS_dz ! Vertical gradient of salinity [ppt Z-1 ~> ppt m-1]. + real :: S_sur, S_bot ! Salinity at the surface and bottom [S ~> ppt] + real :: T_sur, T_bot ! Temperature at the surface and bottom [C ~> degC] + real :: dT_dz ! Vertical gradient of temperature [C Z-1 ~> degC m-1]. + real :: dS_dz ! Vertical gradient of salinity [S Z-1 ~> ppt m-1]. !character(len=256) :: mesg ! The text of an error message character(len=40) :: verticalCoordinate !real :: rho_tmp logical :: fit_salin ! If true, accept the prescribed temperature and fit the salinity. - real :: T0(SZK_(GV)) ! A profile of temperatures [degC] - real :: S0(SZK_(GV)) ! A profile of salinities [ppt] - real :: drho_dT(SZK_(GV)) ! Derivative of density with temperature [R degC-1 ~> kg m-3 degC-1]. - real :: drho_dS(SZK_(GV)) ! Derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1]. + real :: T0(SZK_(GV)) ! A profile of temperatures [C ~> degC] + real :: S0(SZK_(GV)) ! A profile of salinities [S ~> ppt] + real :: drho_dT(SZK_(GV)) ! Derivative of density with temperature [R C-1 ~> kg m-3 degC-1]. + real :: drho_dS(SZK_(GV)) ! Derivative of density with salinity [R S-1 ~> kg m-3 ppt-1]. real :: rho_guess(SZK_(GV)) ! Potential density at T0 & S0 [R ~> kg m-3]. real :: pres(SZK_(GV)) ! An array of the reference pressure [R L2 T-2 ~> Pa]. (zero here) - real :: drho_dT1 ! A prescribed derivative of density with temperature [R degC-1 ~> kg m-3 degC-1] - real :: drho_dS1 ! A prescribed derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1]. + real :: drho_dT1 ! A prescribed derivative of density with temperature [R C-1 ~> kg m-3 degC-1] + real :: drho_dS1 ! A prescribed derivative of density with salinity [R S-1 ~> kg m-3 ppt-1]. real :: T_Ref, S_Ref is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke pres(:) = 0.0 @@ -284,18 +290,22 @@ subroutine ISOMIP_initialize_temperature_salinity ( T, S, h, depth_tot, G, GV, U call get_param(param_file, mdl, "REGRIDDING_COORDINATE_MODE", verticalCoordinate, & default=DEFAULT_COORDINATE_MODE, do_not_log=just_read) call get_param(param_file, mdl, "ISOMIP_T_SUR",t_sur, & - "Temperature at the surface (interface)", units="degC", default=-1.9, do_not_log=just_read) + "Temperature at the surface (interface)", & + units="degC", default=-1.9, scale=US%degC_to_C, do_not_log=just_read) call get_param(param_file, mdl, "ISOMIP_S_SUR", s_sur, & - "Salinity at the surface (interface)", units="ppt", default=33.8, do_not_log=just_read) + "Salinity at the surface (interface)", & + units="ppt", default=33.8, scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl, "ISOMIP_T_BOT", t_bot, & - "Temperature at the bottom (interface)", units="degC", default=-1.9, do_not_log=just_read) + "Temperature at the bottom (interface)", & + units="degC", default=-1.9, scale=US%degC_to_C, do_not_log=just_read) call get_param(param_file, mdl, "ISOMIP_S_BOT", s_bot, & - "Salinity at the bottom (interface)", units="ppt", default=34.55, do_not_log=just_read) + "Salinity at the bottom (interface)", & + units="ppt", default=34.55, scale=US%ppt_to_S, do_not_log=just_read) - call calculate_density(t_sur, s_sur, 0.0, rho_sur, eqn_of_state) + call calculate_density(T_sur, S_sur, 0.0, rho_sur, eqn_of_state) ! write(mesg,*) 'Density in the surface layer:', rho_sur ! call MOM_mesg(mesg,5) - call calculate_density(t_bot, s_bot, 0.0, rho_bot, eqn_of_state) + call calculate_density(T_bot, S_bot, 0.0, rho_bot, eqn_of_state) ! write(mesg,*) 'Density in the bottom layer::', rho_bot ! call MOM_mesg(mesg,5) @@ -304,8 +314,8 @@ subroutine ISOMIP_initialize_temperature_salinity ( T, S, h, depth_tot, G, GV, U case ( REGRIDDING_RHO, REGRIDDING_ZSTAR, REGRIDDING_SIGMA_SHELF_ZSTAR, REGRIDDING_SIGMA ) if (just_read) return ! All run-time parameters have been read, so return. - dS_dz = (s_sur - s_bot) / G%max_depth - dT_dz = (t_sur - t_bot) / G%max_depth + dS_dz = (S_sur - S_bot) / G%max_depth + dT_dz = (T_sur - T_bot) / G%max_depth do j=js,je ; do i=is,ie xi0 = -depth_tot(i,j) do k = nz,1,-1 @@ -323,23 +333,25 @@ subroutine ISOMIP_initialize_temperature_salinity ( T, S, h, depth_tot, G, GV, U default=.false., do_not_log=just_read) call get_param(param_file, mdl, "DRHO_DS", drho_dS1, & "Partial derivative of density with salinity.", & - units="kg m-3 PSU-1", scale=US%kg_m3_to_R, fail_if_missing=.not.just_read, do_not_log=just_read) + units="kg m-3 PSU-1", scale=US%kg_m3_to_R*US%S_to_ppt, & + fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl, "DRHO_DT", drho_dT1, & "Partial derivative of density with temperature.", & - units="kg m-3 K-1", scale=US%kg_m3_to_R, fail_if_missing=.not.just_read, do_not_log=just_read) + units="kg m-3 K-1", scale=US%kg_m3_to_R*US%C_to_degC, & + fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl, "T_REF", T_Ref, & "A reference temperature used in initialization.", & - units="degC", fail_if_missing=.not.just_read, do_not_log=just_read) + units="degC", scale=US%degC_to_C, fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl, "S_REF", S_Ref, & "A reference salinity used in initialization.", units="PSU", & - default=35.0, do_not_log=just_read) + default=35.0, scale=US%ppt_to_S, do_not_log=just_read) if (just_read) return ! All run-time parameters have been read, so return. ! write(mesg,*) 'read drho_dS, drho_dT', drho_dS1, drho_dT1 ! call MOM_mesg(mesg,5) - dS_dz = (s_sur - s_bot) / G%max_depth - dT_dz = (t_sur - t_bot) / G%max_depth + dS_dz = (S_sur - S_bot) / G%max_depth + dT_dz = (T_sur - T_bot) / G%max_depth do j=js,je ; do i=is,ie xi0 = 0.0 @@ -402,8 +414,8 @@ subroutine ISOMIP_initialize_temperature_salinity ( T, S, h, depth_tot, G, GV, U ! for debugging !i=G%iec; j=G%jec !do k = 1,nz - ! call calculate_density(T(i,j,k),S(i,j,k),0.0,rho_tmp,eqn_of_state, scale=US%kg_m3_to_R) - ! write(mesg,*) 'k,h,T,S,rho,Rlay',k,h(i,j,k),T(i,j,k),S(i,j,k),rho_tmp,GV%Rlay(k) + ! call calculate_density(T(i,j,k), S(i,j,k),0.0,rho_tmp,eqn_of_state, scale=US%kg_m3_to_R) + ! write(mesg,*) 'k,h,T,S,rho,Rlay',k,h(i,j,k),US%C_to_degC*T(i,j,k),US%S_to_ppt*S(i,j,k),rho_tmp,GV%Rlay(k) ! call MOM_mesg(mesg,5) !enddo @@ -430,18 +442,19 @@ subroutine ISOMIP_initialize_sponges(G, GV, US, tv, depth_tot, PF, use_ALE, CSp, type(sponge_CS), pointer :: CSp !< Layer-mode sponge structure type(ALE_sponge_CS), pointer :: ACSp !< ALE-mode sponge structure ! Local variables - real :: T(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for temp [degC] - real :: S(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for salt [ppt] + real :: T(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for temp [C ~> degC] + real :: S(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for salt [S ~> ppt] ! real :: RHO(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for RHO [R ~> kg m-3] real :: h(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for thickness [H ~> m or kg m-2] real :: Idamp(SZI_(G),SZJ_(G)) ! The sponge damping rate [T-1 ~> s-1] real :: TNUDG ! Nudging time scale [T ~> s] - real :: S_sur, T_sur ! Surface salinity and temerature in sponge - real :: S_bot, T_bot ! Bottom salinity and temerature in sponge - real :: t_ref, s_ref ! reference T and S + real :: S_sur, S_bot ! Surface and bottom salinities in the sponge region [S ~> ppt] + real :: T_sur, T_bot ! Surface and bottom temperatures in the sponge region [C ~> degC] + real :: t_ref, s_ref ! reference (default) T [degC] and S [ppt] real :: rho_sur, rho_bot ! Surface and bottom densities [R ~> kg m-3] real :: rho_range ! The range of densities [R ~> kg m-3] - real :: dT_dz, dS_dz ! Gradients of T and S in degC/Z and PPT/Z. + real :: dT_dz ! Vertical gradient of temperature [C Z-1 ~> degC m-1] + real :: dS_dz ! Vertical gradient of salinity [S Z-1 ~> ppt m-1] real :: e0(SZK_(GV)+1) ! The resting interface heights [Z ~> m], usually ! negative because it is positive upward. @@ -475,16 +488,20 @@ subroutine ISOMIP_initialize_sponges(G, GV, US, tv, depth_tot, PF, use_ALE, CSp, do_not_log=.true.) call get_param(PF, mdl, "ISOMIP_S_SUR_SPONGE", s_sur, & - "Surface salinity in sponge layer.", units="ppt", default=s_ref) ! units="ppt") + "Surface salinity in sponge layer.", & + units="ppt", default=s_ref, scale=US%ppt_to_S) ! units="ppt") call get_param(PF, mdl, "ISOMIP_S_BOT_SPONGE", s_bot, & - "Bottom salinity in sponge layer.", units="ppt", default=s_ref) ! units="ppt") + "Bottom salinity in sponge layer.", & + units="ppt", default=s_ref, scale=US%ppt_to_S) ! units="ppt") call get_param(PF, mdl, "ISOMIP_T_SUR_SPONGE", t_sur, & - "Surface temperature in sponge layer.", units="degC", default=t_ref) ! units="degC") + "Surface temperature in sponge layer.", & + units="degC", default=t_ref, scale=US%degC_to_C) call get_param(PF, mdl, "ISOMIP_T_BOT_SPONGE", t_bot, & - "Bottom temperature in sponge layer.", units="degC", default=t_ref) ! units="degC") + "Bottom temperature in sponge layer.", & + units="degC", default=t_ref, scale=US%degC_to_C) T(:,:,:) = 0.0 ; S(:,:,:) = 0.0 ; Idamp(:,:) = 0.0 !; RHO(:,:,:) = 0.0 @@ -515,10 +532,10 @@ subroutine ISOMIP_initialize_sponges(G, GV, US, tv, depth_tot, PF, use_ALE, CSp, enddo ; enddo ! Compute min/max density using T_SUR/S_SUR and T_BOT/S_BOT - call calculate_density(t_sur, s_sur, 0.0, rho_sur, tv%eqn_of_state) + call calculate_density(T_sur, S_sur, 0.0, rho_sur, tv%eqn_of_state) !write (mesg,*) 'Surface density in sponge:', rho_sur ! call MOM_mesg(mesg,5) - call calculate_density(t_bot, s_bot, 0.0, rho_bot, tv%eqn_of_state) + call calculate_density(T_bot, S_bot, 0.0, rho_bot, tv%eqn_of_state) !write (mesg,*) 'Bottom density in sponge:', rho_bot ! call MOM_mesg(mesg,5) rho_range = rho_bot - rho_sur @@ -585,8 +602,8 @@ subroutine ISOMIP_initialize_sponges(G, GV, US, tv, depth_tot, PF, use_ALE, CSp, ! This sets the inverse damping timescale fields in the sponges. call initialize_ALE_sponge(Idamp, G, GV, PF, ACSp, h, nz) - dS_dz = (s_sur - s_bot) / G%max_depth - dT_dz = (t_sur - t_bot) / G%max_depth + dS_dz = (S_sur - S_bot) / G%max_depth + dT_dz = (T_sur - T_bot) / G%max_depth do j=js,je ; do i=is,ie xi0 = -depth_tot(i,j) do k = nz,1,-1 @@ -599,7 +616,7 @@ subroutine ISOMIP_initialize_sponges(G, GV, US, tv, depth_tot, PF, use_ALE, CSp, ! for debugging !i=G%iec; j=G%jec !do k = 1,nz - ! call calculate_density(T(i,j,k),S(i,j,k),0.0,rho_tmp,tv%eqn_of_state, scale=US%kg_m3_to_R) + ! call calculate_density(T(i,j,k), S(i,j,k), 0.0, rho_tmp, tv%eqn_of_state, scale=US%kg_m3_to_R) ! write(mesg,*) 'Sponge - k,h,T,S,rho,Rlay',k,h(i,j,k),T(i,j,k),S(i,j,k),rho_tmp,GV%Rlay(k) ! call MOM_mesg(mesg,5) !enddo @@ -643,13 +660,13 @@ subroutine ISOMIP_initialize_sponges(G, GV, US, tv, depth_tot, PF, use_ALE, CSp, if (.not.file_exists(filename, G%Domain)) call MOM_error(FATAL, & "ISOMIP_initialize_sponges: Unable to open "//trim(filename)) call MOM_read_data(filename, eta_var, eta(:,:,:), G%Domain, scale=US%m_to_Z) - call MOM_read_data(filename, temp_var, T(:,:,:), G%Domain) - call MOM_read_data(filename, salt_var, S(:,:,:), G%Domain) + call MOM_read_data(filename, temp_var, T(:,:,:), G%Domain, scale=US%degC_to_C) + call MOM_read_data(filename, salt_var, S(:,:,:), G%Domain, scale=US%ppt_to_S) ! for debugging !i=G%iec; j=G%jec !do k = 1,nz - ! call calculate_density(T(i,j,k),S(i,j,k),0.0,rho_tmp,tv%eqn_of_state, scale=US%kg_m3_to_R) + ! call calculate_density(T(i,j,k), S(i,j,k), 0.0, rho_tmp, tv%eqn_of_state, scale=US%kg_m3_to_R) ! write(mesg,*) 'Sponge - k,eta,T,S,rho,Rlay',k,eta(i,j,k),T(i,j,k),& ! S(i,j,k),rho_tmp,GV%Rlay(k) ! call MOM_mesg(mesg,5) diff --git a/src/user/Phillips_initialization.F90 b/src/user/Phillips_initialization.F90 index f4f18869c4..97d26f7ee2 100644 --- a/src/user/Phillips_initialization.F90 +++ b/src/user/Phillips_initialization.F90 @@ -383,8 +383,8 @@ end subroutine Phillips_initialize_topography !! D - Basin depth [Z ~> m] (positive downward) !! f - The Coriolis parameter [T-1 ~> s-1]. !! If ENABLE_THERMODYNAMICS is defined: -!! T - Temperature [degC]. -!! S - Salinity [ppt]. +!! T - Temperature [C ~> degC]. +!! S - Salinity [S ~> ppt]. !! If SPONGE is defined: !! A series of subroutine calls are made to set up the damping !! rates and reference profiles for all variables that are damped diff --git a/src/user/RGC_initialization.F90 b/src/user/RGC_initialization.F90 index 8e4026a444..d9c1846a0e 100644 --- a/src/user/RGC_initialization.F90 +++ b/src/user/RGC_initialization.F90 @@ -58,8 +58,8 @@ subroutine RGC_initialize_sponges(G, GV, US, tv, u, v, depth_tot, PF, use_ALE, C type(ALE_sponge_CS), pointer :: ACSp !< ALE-mode sponge structure ! Local variables - real :: T(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for temperature [degC] - real :: S(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for salinity [ppt] + real :: T(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for temperature [C ~> degC] + real :: S(SZI_(G),SZJ_(G),SZK_(GV)) ! A temporary array for salinity [S ~> ppt] real :: U1(SZIB_(G),SZJ_(G),SZK_(GV)) ! A temporary array for u [L T-1 ~> m s-1] real :: V1(SZI_(G),SZJB_(G),SZK_(GV)) ! A temporary array for v [L T-1 ~> m s-1] real :: tmp(SZI_(G),SZJ_(G)) ! A temporary array for tracers. @@ -158,8 +158,8 @@ subroutine RGC_initialize_sponges(G, GV, US, tv, u, v, depth_tot, PF, use_ALE, C filename = trim(inputdir)//trim(state_file) if (.not.file_exists(filename, G%Domain)) & call MOM_error(FATAL, " RGC_initialize_sponges: Unable to open "//trim(filename)) - call MOM_read_data(filename, temp_var, T(:,:,:), G%Domain) - call MOM_read_data(filename, salt_var, S(:,:,:), G%Domain) + call MOM_read_data(filename, temp_var, T(:,:,:), G%Domain, scale=US%degC_to_C) + call MOM_read_data(filename, salt_var, S(:,:,:), G%Domain, scale=US%ppt_to_S) if (use_ALE) then call MOM_read_data(filename, h_var, h(:,:,:), G%Domain, scale=GV%m_to_H) diff --git a/src/user/Rossby_front_2d_initialization.F90 b/src/user/Rossby_front_2d_initialization.F90 index b491c027f3..2d0dcb85e5 100644 --- a/src/user/Rossby_front_2d_initialization.F90 +++ b/src/user/Rossby_front_2d_initialization.F90 @@ -105,13 +105,14 @@ end subroutine Rossby_front_initialize_thickness !> Initialization of temperature and salinity in the Rossby front test -subroutine Rossby_front_initialize_temperature_salinity(T, S, h, G, GV, & +subroutine Rossby_front_initialize_temperature_salinity(T, S, h, G, GV, US, & param_file, just_read) type(ocean_grid_type), intent(in) :: G !< Grid structure type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure. - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Thickness [H ~> m or kg m-2] + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< Parameter file handle logical, intent(in) :: just_read !< If true, this call will !! only read parameters without changing T & S. @@ -127,11 +128,11 @@ subroutine Rossby_front_initialize_temperature_salinity(T, S, h, G, GV, & call get_param(param_file, mdl,"REGRIDDING_COORDINATE_MODE", verticalCoordinate, & default=DEFAULT_COORDINATE_MODE, do_not_log=just_read) call get_param(param_file, mdl, "S_REF", S_ref, 'Reference salinity', & - default=35.0, units='1e-3', do_not_log=just_read) - call get_param(param_file, mdl,"T_REF",T_ref,'Reference temperature',units='C',& - fail_if_missing=.not.just_read, do_not_log=just_read) + default=35.0, units='1e-3', scale=US%ppt_to_S, do_not_log=just_read) + call get_param(param_file, mdl,"T_REF",T_ref,'Reference temperature', & + units='C', scale=US%degC_to_C, fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl,"T_RANGE",T_range,'Initial temperature range',& - units='C', default=0.0, do_not_log=just_read) + units='C', default=0.0, scale=US%degC_to_C, do_not_log=just_read) if (just_read) return ! All run-time parameters have been read, so return. diff --git a/src/user/SCM_CVMix_tests.F90 b/src/user/SCM_CVMix_tests.F90 index 74cf31a22b..64a834e062 100644 --- a/src/user/SCM_CVMix_tests.F90 +++ b/src/user/SCM_CVMix_tests.F90 @@ -55,8 +55,8 @@ module SCM_CVMix_tests subroutine SCM_CVMix_tests_TS_init(T, S, h, G, GV, US, param_file, just_read) type(ocean_grid_type), intent(in) :: G !< Grid structure type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2] type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< Input parameter structure @@ -65,13 +65,13 @@ subroutine SCM_CVMix_tests_TS_init(T, S, h, G, GV, US, param_file, just_read) ! Local variables real :: UpperLayerTempMLD !< Upper layer Temp MLD thickness [Z ~> m]. real :: UpperLayerSaltMLD !< Upper layer Salt MLD thickness [Z ~> m]. - real :: UpperLayerTemp !< Upper layer temperature (SST if thickness 0) [degC] - real :: UpperLayerSalt !< Upper layer salinity (SSS if thickness 0) [ppt] - real :: LowerLayerTemp !< Temp at top of lower layer [degC] - real :: LowerLayerSalt !< Salt at top of lower layer [ppt] - real :: LowerLayerdTdz !< Temp gradient in lower layer [degC Z-1 ~> degC m-1]. - real :: LowerLayerdSdz !< Salt gradient in lower layer [ppt Z-1 ~> ppt m-1]. - real :: LowerLayerMinTemp !< Minimum temperature in lower layer [degC] + real :: UpperLayerTemp !< Upper layer temperature (SST if thickness 0) [C ~> degC] + real :: UpperLayerSalt !< Upper layer salinity (SSS if thickness 0) [S ~> ppt] + real :: LowerLayerTemp !< Temp at top of lower layer [C ~> degC] + real :: LowerLayerSalt !< Salt at top of lower layer [S ~> ppt] + real :: LowerLayerdTdz !< Temp gradient in lower layer [C Z-1 ~> degC m-1]. + real :: LowerLayerdSdz !< Salt gradient in lower layer [S Z-1 ~> ppt m-1]. + real :: LowerLayerMinTemp !< Minimum temperature in lower layer [C ~> degC] real :: zC, DZ, top, bottom ! Depths and thicknesses [Z ~> m]. integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz @@ -86,21 +86,21 @@ subroutine SCM_CVMix_tests_TS_init(T, S, h, G, GV, US, param_file, just_read) 'Initial salt mixed layer depth', & units='m', default=0.0, scale=US%m_to_Z, do_not_log=just_read) call get_param(param_file, mdl, "SCM_L1_SALT", UpperLayerSalt, & - 'Layer 2 surface salinity', units='1e-3', default=35.0, do_not_log=just_read) + 'Layer 2 surface salinity', units='1e-3', default=35.0, scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl, "SCM_L1_TEMP", UpperLayerTemp, & - 'Layer 1 surface temperature', units='C', default=20.0, do_not_log=just_read) + 'Layer 1 surface temperature', units='C', default=20.0, scale=US%degC_to_C, do_not_log=just_read) call get_param(param_file, mdl, "SCM_L2_SALT", LowerLayerSalt, & - 'Layer 2 surface salinity', units='1e-3', default=35.0, do_not_log=just_read) + 'Layer 2 surface salinity', units='1e-3', default=35.0, scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl, "SCM_L2_TEMP", LowerLayerTemp, & - 'Layer 2 surface temperature', units='C', default=20.0, do_not_log=just_read) + 'Layer 2 surface temperature', units='C', default=20.0, scale=US%degC_to_C, do_not_log=just_read) call get_param(param_file, mdl, "SCM_L2_DTDZ", LowerLayerdTdZ, & 'Initial temperature stratification in layer 2', & - units='C/m', default=0.0, scale=US%Z_to_m, do_not_log=just_read) + units='C/m', default=0.0, scale=US%degC_to_C*US%Z_to_m, do_not_log=just_read) call get_param(param_file, mdl, "SCM_L2_DSDZ", LowerLayerdSdZ, & 'Initial salinity stratification in layer 2', & - units='PPT/m', default=0.0, scale=US%Z_to_m, do_not_log=just_read) + units='PPT/m', default=0.0, scale=US%ppt_to_S*US%Z_to_m, do_not_log=just_read) call get_param(param_file, mdl, "SCM_L2_MINTEMP",LowerLayerMinTemp, & - 'Layer 2 minimum temperature', units='C', default=4.0, do_not_log=just_read) + 'Layer 2 minimum temperature', units='C', default=4.0, scale=US%degC_to_C, do_not_log=just_read) if (just_read) return ! All run-time parameters have been read, so return. diff --git a/src/user/adjustment_initialization.F90 b/src/user/adjustment_initialization.F90 index 6c05def460..3509ef69d3 100644 --- a/src/user/adjustment_initialization.F90 +++ b/src/user/adjustment_initialization.F90 @@ -46,10 +46,14 @@ subroutine adjustment_initialize_thickness ( h, G, GV, US, param_file, just_read ! negative because it is positive upward. real :: eta1D(SZK_(GV)+1) ! Interface height relative to the sea surface ! positive upward, in depth units [Z ~> m]. - real :: dRho_dS ! The partial derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1]. + real :: dRho_dS ! The partial derivative of density with salinity [R S-1 ~> kg m-3 ppt-1]. ! In this subroutine it is hard coded at 1.0 kg m-3 ppt-1. real :: x, y, yy - real :: delta_S_strat, dSdz, delta_S, S_ref + real :: S_ref ! Reference salinity within surface layer [S ~> ppt] + real :: S_range ! Range of salinities in the vertical [S ~> ppt] + real :: dSdz ! Vertical salinity gradient [S Z-1 ~> ppt m-1] + real :: delta_S ! The local salinity perturbation [S ~> ppt] + real :: delta_S_strat ! Top-to-bottom salinity difference of stratification [S ~> ppt] real :: min_thickness, adjustment_width, adjustment_delta real :: adjustment_deltaS real :: front_wave_amp, front_wave_length, front_wave_asym @@ -67,7 +71,7 @@ subroutine adjustment_initialize_thickness ( h, G, GV, US, param_file, just_read ! Parameters used by main model initialization if (.not.just_read) call log_version(param_file, mdl, version, "") call get_param(param_file, mdl, "S_REF", S_ref, 'Reference salinity', & - default=35.0, units='1e-3', do_not_log=just_read) + default=35.0, units='1e-3', scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl,"MIN_THICKNESS",min_thickness,'Minimum layer thickness', & default=1.0e-3, units='m', scale=US%m_to_Z, do_not_log=just_read) @@ -79,10 +83,10 @@ subroutine adjustment_initialize_thickness ( h, G, GV, US, param_file, just_read units="same as x,y", fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl,"DELTA_S_STRAT",delta_S_strat, & "Top-to-bottom salinity difference of stratification", & - units="1e-3", fail_if_missing=.not.just_read, do_not_log=just_read) + units="1e-3", scale=US%ppt_to_S, fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl,"ADJUSTMENT_DELTAS",adjustment_deltaS, & "Salinity difference across front", & - units="1e-3", fail_if_missing=.not.just_read, do_not_log=just_read) + units="1e-3", scale=US%ppt_to_S, fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl,"FRONT_WAVE_AMP",front_wave_amp, & "Amplitude of trans-frontal wave perturbation", & units="same as x,y", default=0., do_not_log=just_read) @@ -108,7 +112,7 @@ subroutine adjustment_initialize_thickness ( h, G, GV, US, param_file, just_read select case ( coordinateMode(verticalCoordinate) ) case ( REGRIDDING_LAYER, REGRIDDING_RHO ) - dRho_dS = 1.0 * US%kg_m3_to_R + dRho_dS = 1.0*US%kg_m3_to_R*US%S_to_ppt if (delta_S_strat /= 0.) then ! This was previously coded ambiguously. adjustment_delta = (adjustment_deltaS / delta_S_strat) * G%max_depth @@ -131,7 +135,7 @@ subroutine adjustment_initialize_thickness ( h, G, GV, US, param_file, just_read do k = 2,nz target_values(k) = target_values(k-1) + ( GV%Rlay(nz) - GV%Rlay(1) ) / (nz-1) enddo - target_values(:) = target_values(:) - 1000.*US%kg_m3_to_R + target_values(:) = target_values(:) - 1000.0*US%kg_m3_to_R do j=js,je ; do i=is,ie if (front_wave_length /= 0.) then y = ( 0.125 + G%geoLatT(i,j) / front_wave_length ) * ( 4. * acos(0.) ) @@ -189,11 +193,12 @@ subroutine adjustment_initialize_thickness ( h, G, GV, US, param_file, just_read end subroutine adjustment_initialize_thickness !> Initialization of temperature and salinity in the adjustment test case -subroutine adjustment_initialize_temperature_salinity(T, S, h, depth_tot, G, GV, param_file, just_read) +subroutine adjustment_initialize_temperature_salinity(T, S, h, depth_tot, G, GV, US, param_file, just_read) 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(out) :: T !< The temperature that is being initialized. - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< The salinity that is being initialized. + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< The temperature that is being initialized [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< The salinity that is being initialized [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< The model thicknesses [H ~> m or kg m-2]. real, dimension(SZI_(G),SZJ_(G)), & intent(in) :: depth_tot !< The nominal total depth of the ocean [Z ~> m] @@ -204,36 +209,39 @@ subroutine adjustment_initialize_temperature_salinity(T, S, h, depth_tot, G, GV, integer :: i, j, k, is, ie, js, je, nz real :: x, y, yy - real :: S_ref, T_ref ! Reference salinity and temerature within - ! surface layer - real :: S_range, T_range ! Range of salinities and temperatures over the - ! vertical - real :: dSdz, delta_S, delta_S_strat - real :: adjustment_width, adjustment_deltaS - real :: front_wave_amp, front_wave_length, front_wave_asym - real :: eta1d(SZK_(GV)+1) + real :: S_ref ! Reference salinity within surface layer [S ~> ppt] + real :: T_ref ! Reference temperature within surface layer [C ~> degC] + real :: S_range ! Range of salinities in the vertical [S ~> ppt] + real :: T_range ! Range of temperatures in the vertical [C ~> degC] + real :: dSdz ! Vertical salinity gradient [S Z-1 ~> ppt m-1] + real :: delta_S ! The local salinity perturbation [S ~> ppt] + real :: delta_S_strat ! Top-to-bottom salinity difference of stratification [S ~> ppt] + real :: adjustment_width + real :: adjustment_deltaS ! Salinity difference across front [S ~> ppt] + real :: front_wave_amp, front_wave_length, front_wave_asym + real :: eta1d(SZK_(GV)+1) ! Interface heights [Z ~> m] character(len=20) :: verticalCoordinate is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke ! Parameters used by main model initialization call get_param(param_file, mdl, "S_REF", S_ref, 'Reference salinity', & - default=35.0, units='1e-3', do_not_log=just_read) - call get_param(param_file, mdl,"T_REF",T_ref,'Reference temperature', units='C', & - fail_if_missing=.not.just_read, do_not_log=just_read) - call get_param(param_file, mdl,"S_RANGE",S_range,'Initial salinity range', units='1e-3', & - default=2.0, do_not_log=just_read) - call get_param(param_file, mdl,"T_RANGE",T_range,'Initial temperature range', units='C', & - default=0.0, do_not_log=just_read) + default=35.0, units='1e-3', scale=US%ppt_to_S, do_not_log=just_read) + call get_param(param_file, mdl,"T_REF",T_ref,'Reference temperature', & + units='C', scale=US%degC_to_C, fail_if_missing=.not.just_read, do_not_log=just_read) + call get_param(param_file, mdl,"S_RANGE", S_range, 'Initial salinity range', & + default=2.0, units='1e-3', scale=US%ppt_to_S, do_not_log=just_read) + call get_param(param_file, mdl,"T_RANGE",T_range,'Initial temperature range', & + default=0.0, units='C', scale=US%degC_to_C, do_not_log=just_read) ! Parameters specific to this experiment configuration BUT logged in previous s/r call get_param(param_file, mdl,"REGRIDDING_COORDINATE_MODE",verticalCoordinate, & default=DEFAULT_COORDINATE_MODE, do_not_log=just_read) call get_param(param_file, mdl,"ADJUSTMENT_WIDTH", adjustment_width, & fail_if_missing=.not.just_read, do_not_log=.true.) call get_param(param_file, mdl,"ADJUSTMENT_DELTAS", adjustment_deltaS, & - fail_if_missing=.not.just_read, do_not_log=.true.) + units='1e-3', scale=US%ppt_to_S, fail_if_missing=.not.just_read, do_not_log=.true.) call get_param(param_file, mdl,"DELTA_S_STRAT", delta_S_strat, & - fail_if_missing=.not.just_read, do_not_log=.true.) + units='1e-3', scale=US%ppt_to_S, fail_if_missing=.not.just_read, do_not_log=.true.) call get_param(param_file, mdl,"FRONT_WAVE_AMP", front_wave_amp, default=0., & do_not_log=.true.) call get_param(param_file, mdl,"FRONT_WAVE_LENGTH",front_wave_length, & @@ -273,7 +281,7 @@ subroutine adjustment_initialize_temperature_salinity(T, S, h, depth_tot, G, GV, S(i,j,k) = S_ref + delta_S + 0.5 * ( eta1D(k)+eta1D(k+1) ) * dSdz x = abs(S(i,j,k) - 0.5*real(nz-1)/real(nz)*S_range)/S_range*real(2*nz) x = 1. - min(1., x) - T(i,j,k) = x + T(i,j,k) = US%degC_to_C * x enddo ! x = GV%H_to_Z*sum(T(i,j,:)*h(i,j,:)) ! T(i,j,:) = (T(i,j,:) / x) * (G%max_depth*1.5/real(nz)) diff --git a/src/user/baroclinic_zone_initialization.F90 b/src/user/baroclinic_zone_initialization.F90 index a214012541..eb1f943b87 100644 --- a/src/user/baroclinic_zone_initialization.F90 +++ b/src/user/baroclinic_zone_initialization.F90 @@ -33,14 +33,16 @@ subroutine bcz_params(G, GV, US, param_file, S_ref, dSdz, delta_S, dSdx, T_ref, type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure. type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< Parameter file handle - real, intent(out) :: S_ref !< Reference salinity [ppt] - real, intent(out) :: dSdz !< Salinity stratification [ppt Z-1 ~> ppt m-1] - real, intent(out) :: delta_S !< Salinity difference across baroclinic zone [ppt] - real, intent(out) :: dSdx !< Linear salinity gradient [ppt G%xaxis_units-1] - real, intent(out) :: T_ref !< Reference temperature [degC] - real, intent(out) :: dTdz !< Temperature stratification [degC Z-1 ~> degC m-1] - real, intent(out) :: delta_T !< Temperature difference across baroclinic zone [degC] - real, intent(out) :: dTdx !< Linear temperature gradient in [degC G%x_axis_units-1] + real, intent(out) :: S_ref !< Reference salinity [S ~> ppt] + real, intent(out) :: dSdz !< Salinity stratification [S Z-1 ~> ppt m-1] + real, intent(out) :: delta_S !< Salinity difference across baroclinic zone [S ~> ppt] + real, intent(out) :: dSdx !< Linear salinity gradient + !! in [S G%xaxis_units-1 ~> ppt G%xaxis_units-1] + real, intent(out) :: T_ref !< Reference temperature [C ~> degC] + real, intent(out) :: dTdz !< Temperature stratification [C Z-1 ~> degC m-1] + real, intent(out) :: delta_T !< Temperature difference across baroclinic zone [C ~> degC] + real, intent(out) :: dTdx !< Linear temperature gradient + !! in [C G%x_axis_units-1 ~> degC G%x_axis_units-1] real, intent(out) :: L_zone !< Width of baroclinic zone in [G%x_axis_units] logical, intent(in) :: just_read !< If true, this call will !! only read parameters without changing h. @@ -48,22 +50,22 @@ subroutine bcz_params(G, GV, US, param_file, S_ref, dSdz, delta_S, dSdx, T_ref, if (.not.just_read) & call log_version(param_file, mdl, version, 'Initialization of an analytic baroclinic zone') call openParameterBlock(param_file,'BCZIC') - call get_param(param_file, mdl, "S_REF", S_ref, 'Reference salinity', units='ppt', & - default=35., do_not_log=just_read) + call get_param(param_file, mdl, "S_REF", S_ref, 'Reference salinity', & + units='ppt', default=35., scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl, "DSDZ", dSdz, 'Salinity stratification', & - units='ppt/m', default=0.0, scale=US%Z_to_m, do_not_log=just_read) + units='ppt/m', default=0.0, scale=US%ppt_to_S*US%Z_to_m, do_not_log=just_read) call get_param(param_file, mdl,"DELTA_S",delta_S,'Salinity difference across baroclinic zone', & - units='ppt', default=0.0, do_not_log=just_read) + units='ppt', default=0.0, scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl,"DSDX",dSdx,'Meridional salinity difference', & - units='ppt/'//trim(G%x_axis_units), default=0.0, do_not_log=just_read) - call get_param(param_file, mdl,"T_REF",T_ref,'Reference temperature',units='C', & - default=10., do_not_log=just_read) + units='ppt/'//trim(G%x_axis_units), default=0.0, scale=US%ppt_to_S, do_not_log=just_read) + call get_param(param_file, mdl,"T_REF",T_ref,'Reference temperature', & + units='C', default=10., scale=US%degC_to_C, do_not_log=just_read) call get_param(param_file, mdl, "DTDZ", dTdz, 'Temperature stratification', & - units='C/m', default=0.0, scale=US%Z_to_m, do_not_log=just_read) + units='C/m', default=0.0, scale=US%degC_to_C*US%Z_to_m, do_not_log=just_read) call get_param(param_file, mdl,"DELTA_T",delta_T,'Temperature difference across baroclinic zone', & - units='C', default=0.0, do_not_log=just_read) + units='C', default=0.0, scale=US%degC_to_C, do_not_log=just_read) call get_param(param_file, mdl,"DTDX",dTdx,'Meridional temperature difference', & - units='C/'//trim(G%x_axis_units), default=0.0, do_not_log=just_read) + units='C/'//trim(G%x_axis_units), default=0.0, scale=US%degC_to_C, do_not_log=just_read) call get_param(param_file, mdl,"L_ZONE",L_zone,'Width of baroclinic zone', & units=G%x_axis_units, default=0.5*G%len_lat, do_not_log=just_read) call closeParameterBlock(param_file) @@ -77,9 +79,9 @@ subroutine baroclinic_zone_init_temperature_salinity(T, S, h, depth_tot, G, GV, type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure. type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(out) :: T !< Potential temperature [degC] + intent(out) :: T !< Potential temperature [C ~> degC] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & - intent(out) :: S !< Salinity [ppt] + intent(out) :: S !< Salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & intent(in) :: h !< The model thicknesses [H ~> m or kg m-2] real, dimension(SZI_(G),SZJ_(G)), & @@ -90,8 +92,8 @@ subroutine baroclinic_zone_init_temperature_salinity(T, S, h, depth_tot, G, GV, !! parameters without changing T & S. integer :: i, j, k, is, ie, js, je, nz - real :: T_ref, dTdz, dTdx, delta_T ! Parameters describing temperature distribution - real :: S_ref, dSdz, dSdx, delta_S ! Parameters describing salinity distribution + real :: T_ref, dTdz, dTdx, delta_T ! Parameters describing temperature distribution [C ~> degC] + real :: S_ref, dSdz, dSdx, delta_S ! Parameters describing salinity distribution [S ~> ppt] real :: L_zone ! Width of baroclinic zone in [G%axis_units] real :: zc, zi ! Depths in depth units [Z ~> m] real :: x, xd, xs, y, yd, fn diff --git a/src/user/benchmark_initialization.F90 b/src/user/benchmark_initialization.F90 index e042e245b7..9ed2881563 100644 --- a/src/user/benchmark_initialization.F90 +++ b/src/user/benchmark_initialization.F90 @@ -101,15 +101,15 @@ subroutine benchmark_initialize_thickness(h, depth_tot, G, GV, US, param_file, e ! in depth units [Z ~> m]. real :: eta1D(SZK_(GV)+1) ! Interface height relative to the sea surface ! positive upward, in depth units [Z ~> m]. - real :: SST ! The initial sea surface temperature [degC]. - real :: T_int ! The initial temperature of an interface [degC]. + real :: SST ! The initial sea surface temperature [C ~> degC]. + real :: T_int ! The initial temperature of an interface [C ~> degC]. real :: ML_depth ! The specified initial mixed layer depth, in depth units [Z ~> m]. real :: thermocline_scale ! The e-folding scale of the thermocline, in depth units [Z ~> m]. real, dimension(SZK_(GV)) :: & - T0, S0, & ! Profiles of temperature [degC] and salinity [ppt] + T0, S0, & ! Profiles of temperature [C ~> degC] and salinity [S ~> ppt] rho_guess, & ! Potential density at T0 & S0 [R ~> kg m-3]. - drho_dT, & ! Derivative of density with temperature [R degC-1 ~> kg m-3 degC-1]. - drho_dS ! Derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1]. + drho_dT, & ! Derivative of density with temperature [R C-1 ~> kg m-3 degC-1]. + drho_dS ! Derivative of density with salinity [R S-1 ~> kg m-3 ppt-1]. real :: pres(SZK_(GV)) ! Reference pressure [R L2 T-2 ~> Pa]. real :: a_exp ! The fraction of the overall stratification that is exponential. real :: I_ts, I_md ! Inverse lengthscales [Z-1 ~> m-1]. @@ -147,9 +147,9 @@ subroutine benchmark_initialize_thickness(h, depth_tot, G, GV, US, param_file, e ! This block calculates T0(k) for the purpose of diagnosing where the ! interfaces will be found. do k=1,nz - pres(k) = P_Ref ; S0(k) = 35.0 + pres(k) = P_Ref ; S0(k) = 35.0*US%ppt_to_S enddo - T0(k1) = 29.0 + T0(k1) = 29.0*US%degC_to_C call calculate_density(T0(k1), S0(k1), pres(k1), rho_guess(k1), eqn_of_state) call calculate_density_derivs(T0(k1), S0(k1), pres(k1), drho_dT(k1), drho_dS(k1), eqn_of_state) @@ -217,9 +217,9 @@ subroutine benchmark_init_temperature_salinity(T, S, G, GV, US, param_file, & 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(out) :: T !< The potential temperature - !! that is being initialized [degC] + !! that is being initialized [C ~> degC] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< The salinity that is being - !! initialized [ppt] + !! initialized [S ~> ppt] type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< A structure indicating the !! open file to parse for @@ -230,14 +230,14 @@ subroutine benchmark_init_temperature_salinity(T, S, G, GV, US, param_file, & logical, intent(in) :: just_read !< If true, this call will only read !! parameters without changing T & S. ! Local variables - real :: T0(SZK_(GV)) ! A profile of temperatures [degC] - real :: S0(SZK_(GV)) ! A profile of salinities [ppt] + real :: T0(SZK_(GV)) ! A profile of temperatures [C ~> degC] + real :: S0(SZK_(GV)) ! A profile of salinities [S ~> ppt] real :: pres(SZK_(GV)) ! Reference pressure [R L2 T-2 ~> Pa] - real :: drho_dT(SZK_(GV)) ! Derivative of density with temperature [R degC-1 ~> kg m-3 degC-1] - real :: drho_dS(SZK_(GV)) ! Derivative of density with salinity [R ppt-1 ~> kg m-3 ppt-1] + real :: drho_dT(SZK_(GV)) ! Derivative of density with temperature [R C-1 ~> kg m-3 degC-1] + real :: drho_dS(SZK_(GV)) ! Derivative of density with salinity [R S-1 ~> kg m-3 ppt-1] real :: rho_guess(SZK_(GV)) ! Potential density at T0 & S0 [R ~> kg m-3] real :: PI ! 3.1415926... calculated as 4*atan(1) - real :: SST ! The initial sea surface temperature [degC] + real :: SST ! The initial sea surface temperature [C ~> degC] integer :: i, j, k, k1, is, ie, js, je, nz, itt is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke @@ -247,10 +247,10 @@ subroutine benchmark_init_temperature_salinity(T, S, G, GV, US, param_file, & k1 = GV%nk_rho_varies + 1 do k=1,nz - pres(k) = P_Ref ; S0(k) = 35.0 + pres(k) = P_Ref ; S0(k) = 35.0*US%ppt_to_S enddo - T0(k1) = 29.0 + T0(k1) = 29.0*US%degC_to_C call calculate_density(T0(k1), S0(k1), pres(k1), rho_guess(k1), eqn_of_state) call calculate_density_derivs(T0, S0, pres, drho_dT, drho_dS, eqn_of_state, (/k1,k1/) ) diff --git a/src/user/dense_water_initialization.F90 b/src/user/dense_water_initialization.F90 index 99836f5ad0..1c372bf1b7 100644 --- a/src/user/dense_water_initialization.F90 +++ b/src/user/dense_water_initialization.F90 @@ -95,12 +95,13 @@ subroutine dense_water_initialize_topography(D, G, param_file, max_depth) end subroutine dense_water_initialize_topography !> Initialize the temperature and salinity for the dense water experiment -subroutine dense_water_initialize_TS(G, GV, param_file, T, S, h, just_read) +subroutine dense_water_initialize_TS(G, GV, US, param_file, T, S, h, just_read) type(ocean_grid_type), intent(in) :: G !< Horizontal grid control structure type(verticalGrid_type), intent(in) :: GV !< Vertical grid control structure + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< Parameter file structure - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Output temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Output salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Output temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Output salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2] logical, intent(in) :: just_read !< If true, this call will !! only read parameters without changing T & S. @@ -115,11 +116,11 @@ subroutine dense_water_initialize_TS(G, GV, param_file, T, S, h, just_read) "Depth of unstratified mixed layer as a fraction of the water column.", & units="nondim", default=default_mld, do_not_log=just_read) call get_param(param_file, mdl, "S_REF", S_ref, 'Reference salinity', & - default=35.0, units='1e-3', do_not_log=just_read) - call get_param(param_file, mdl,"T_REF", T_ref, 'Reference temperature', units='degC', & - fail_if_missing=.not.just_read, do_not_log=just_read) + default=35.0, units='1e-3', scale=US%ppt_to_S, do_not_log=just_read) + call get_param(param_file, mdl,"T_REF", T_ref, 'Reference temperature', & + units='degC', scale=US%degC_to_C, fail_if_missing=.not.just_read, do_not_log=just_read) call get_param(param_file, mdl,"S_RANGE", S_range, 'Initial salinity range', & - units='1e-3', default=2.0, do_not_log=just_read) + units='1e-3', default=2.0, scale=US%ppt_to_S, do_not_log=just_read) if (just_read) return ! All run-time parameters have been read, so return. @@ -165,8 +166,8 @@ subroutine dense_water_initialize_sponges(G, GV, US, tv, depth_tot, param_file, real, dimension(SZI_(G),SZJ_(G)) :: Idamp ! inverse damping timescale [T-1 ~> s-1] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: h ! sponge thicknesses [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: T ! sponge temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: S ! sponge salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: T ! sponge temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: S ! sponge salinity [S ~> ppt] real, dimension(SZK_(GV)+1) :: e0, eta1D ! interface positions for ALE sponge [Z ~> m] integer :: i, j, k, nz @@ -195,9 +196,9 @@ subroutine dense_water_initialize_sponges(G, GV, US, tv, depth_tot, param_file, call get_param(param_file, mdl, "DENSE_WATER_MLD", mld, default=default_mld, do_not_log=.true.) call get_param(param_file, mdl, "DENSE_WATER_SILL_HEIGHT", sill_height, default=default_sill, do_not_log=.true.) - call get_param(param_file, mdl, "S_REF", S_ref, default=35.0, do_not_log=.true.) - call get_param(param_file, mdl, "S_RANGE", S_range, do_not_log=.true.) - call get_param(param_file, mdl, "T_REF", T_ref, do_not_log=.true.) + call get_param(param_file, mdl, "S_REF", S_ref, default=35.0, scale=US%ppt_to_S, do_not_log=.true.) + call get_param(param_file, mdl, "S_RANGE", S_range, scale=US%ppt_to_S, do_not_log=.true.) + call get_param(param_file, mdl, "T_REF", T_ref, scale=US%degC_to_C, do_not_log=.true.) ! no active sponges if (west_sponge_time_scale <= 0. .and. east_sponge_time_scale <= 0.) return diff --git a/src/user/dumbbell_initialization.F90 b/src/user/dumbbell_initialization.F90 index e3d97412bd..c197274067 100644 --- a/src/user/dumbbell_initialization.F90 +++ b/src/user/dumbbell_initialization.F90 @@ -107,7 +107,10 @@ subroutine dumbbell_initialize_thickness ( h, depth_tot, G, GV, US, param_file, real :: eta1D(SZK_(GV)+1) ! Interface height relative to the sea surface ! positive upward [Z ~> m]. real :: min_thickness ! The minimum layer thicknesses [Z ~> m]. - real :: S_surf, S_range, S_ref, S_light, S_dense ! Various salinities [ppt]. + real :: S_ref ! A default value for salinities [ppt]. + real :: S_surf ! The surface salinity [S ~> ppt] + real :: S_range ! The range of salinities in this test case [S ~> ppt] + real :: S_light, S_dense ! The lightest and densest salinities in the sponges [S ~> ppt]. real :: eta_IC_quanta ! The granularity of quantization of intial interface heights [Z-1 ~> m-1]. ! This include declares and sets the variable "version". # include "version_variable.h" @@ -122,7 +125,7 @@ subroutine dumbbell_initialize_thickness ( h, depth_tot, G, GV, US, param_file, if (.not.just_read) call log_version(param_file, mdl, version, "") call get_param(param_file, mdl,"MIN_THICKNESS", min_thickness, & 'Minimum thickness for layer',& - units='m', default=1.0e-3, do_not_log=just_read, scale=US%m_to_Z) + units='m', default=1.0e-3, scale=US%m_to_Z, do_not_log=just_read) call get_param(param_file, mdl,"REGRIDDING_COORDINATE_MODE", verticalCoordinate, & default=DEFAULT_COORDINATE_MODE, do_not_log=just_read) @@ -140,11 +143,15 @@ subroutine dumbbell_initialize_thickness ( h, depth_tot, G, GV, US, param_file, select case ( coordinateMode(verticalCoordinate) ) case ( REGRIDDING_LAYER, REGRIDDING_RHO ) ! Initial thicknesses for isopycnal coordinates - call get_param(param_file, mdl, "INITIAL_SSS", S_surf, default=34., do_not_log=.true.) - call get_param(param_file, mdl, "INITIAL_S_RANGE", S_range, default=2., do_not_log=.true.) + call get_param(param_file, mdl, "INITIAL_SSS", S_surf, & + units='1e-3', default=34., scale=US%ppt_to_S, do_not_log=.true.) + call get_param(param_file, mdl, "INITIAL_S_RANGE", S_range, & + units='1e-3', default=2., scale=US%ppt_to_S, do_not_log=.true.) call get_param(param_file, mdl, "S_REF", S_ref, default=35.0, do_not_log=.true.) - call get_param(param_file, mdl, "TS_RANGE_S_LIGHT", S_light, default = S_Ref, do_not_log=.true.) - call get_param(param_file, mdl, "TS_RANGE_S_DENSE", S_dense, default = S_Ref, do_not_log=.true.) + call get_param(param_file, mdl, "TS_RANGE_S_LIGHT", S_light, & + units='1e-3', default=S_Ref, scale=US%ppt_to_S, do_not_log=.true.) + call get_param(param_file, mdl, "TS_RANGE_S_DENSE", S_dense, & + units='1e-3', default=S_Ref, scale=US%ppt_to_S, do_not_log=.true.) call get_param(param_file, mdl, "INTERFACE_IC_QUANTA", eta_IC_quanta, & "The granularity of initial interface height values "//& "per meter, to avoid sensivity to order-of-arithmetic changes.", & @@ -205,26 +212,30 @@ subroutine dumbbell_initialize_thickness ( h, depth_tot, G, GV, US, param_file, end subroutine dumbbell_initialize_thickness !> Initial values for temperature and salinity for the dumbbell test case -subroutine dumbbell_initialize_temperature_salinity ( T, S, h, G, GV, param_file, just_read) +subroutine dumbbell_initialize_temperature_salinity ( T, S, h, G, GV, US, param_file, just_read) type(ocean_grid_type), intent(in) :: G !< Ocean grid structure - type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [ppt] + type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2] + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< Parameter file structure logical, intent(in) :: just_read !< If true, this call will !! only read parameters without changing h. ! Local variables integer :: i, j, k, is, ie, js, je, nz - real :: S_surf, T_surf, S_range - real :: x, dblen - logical :: dbrotate ! If true, rotate the domain. + real :: S_surf ! The surface salinity [S ~> ppt] + real :: S_range ! The range of salinities in this test case [S ~> ppt] + real :: T_surf ! The surface temperature [C ~> degC] + real :: x ! The fractional position in the domain [nondim] + real :: dblen ! The size of the dumbbell test case [axis_units] + logical :: dbrotate ! If true, rotate the domain. character(len=20) :: verticalCoordinate, density_profile is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke - T_surf = 20.0 + T_surf = 20.0*US%degC_to_C call get_param(param_file, mdl, "REGRIDDING_COORDINATE_MODE", verticalCoordinate, & default=DEFAULT_COORDINATE_MODE, do_not_log=just_read) @@ -232,10 +243,11 @@ subroutine dumbbell_initialize_temperature_salinity ( T, S, h, G, GV, param_file 'Initial profile shape. Valid values are "linear", "parabolic" '// & 'and "exponential".', default='linear', do_not_log=just_read) call get_param(param_file, mdl, "DUMBBELL_SREF", S_surf, & - 'DUMBBELL REFERENCE SALINITY', units='1e-3', default=34., do_not_log=just_read) + 'DUMBBELL REFERENCE SALINITY', & + units='1e-3', default=34., scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl, "DUMBBELL_S_RANGE", S_range, & - 'DUMBBELL salinity range (right-left)', units='1e-3', default=2., & - do_not_log=just_read) + 'DUMBBELL salinity range (right-left)', & + units='1e-3', default=2., scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl, "DUMBBELL_LEN", dblen, & 'Lateral Length scale for dumbbell ', & units='km', default=600., do_not_log=just_read) @@ -291,12 +303,15 @@ subroutine dumbbell_initialize_sponges(G, GV, US, tv, depth_tot, param_file, use real :: sponge_time_scale ! The damping time scale [T ~> s] real, dimension(SZI_(G),SZJ_(G)) :: Idamp ! inverse damping timescale [T-1 ~> s-1] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: h, S ! sponge thicknesses, temp and salt + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: h ! sponge thicknesses [H ~> m or kg m-2] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: S ! sponge salinities [S ~> ppt] real, dimension(SZK_(GV)+1) :: eta1D ! interface positions for ALE sponge integer :: i, j, k, nz - real :: x, min_thickness, dblen - real :: S_ref, S_range + real :: x ! The fractional position in the domain [nondim] + real :: dblen ! The size of the dumbbell test case [axis_units] + real :: min_thickness ! The minimum layer thickness [Z ~> m] + real :: S_ref, S_range ! A reference salinity and the range of salinities in this test case [S ~> ppt] logical :: dbrotate ! If true, rotate the domain. call get_param(param_file, mdl,"DUMBBELL_LEN",dblen, & @@ -315,11 +330,15 @@ subroutine dumbbell_initialize_sponges(G, GV, US, tv, depth_tot, param_file, use call get_param(param_file, mdl, "DUMBBELL_SPONGE_TIME_SCALE", sponge_time_scale, & "The time scale in the reservoir for restoring. If zero, the sponge is disabled.", & units="s", default=0., scale=US%s_to_T) - call get_param(param_file, mdl, "DUMBBELL_SREF", S_ref, do_not_log=.true.) - call get_param(param_file, mdl, "DUMBBELL_S_RANGE", S_range, do_not_log=.true.) + call get_param(param_file, mdl, "DUMBBELL_SREF", S_ref, & + 'DUMBBELL REFERENCE SALINITY', & + units='1e-3', default=34., scale=US%ppt_to_S, do_not_log=.true.) + call get_param(param_file, mdl, "DUMBBELL_S_RANGE", S_range, & + 'DUMBBELL salinity range (right-left)', & + units='1e-3', default=2., scale=US%ppt_to_S, do_not_log=.true.) call get_param(param_file, mdl,"MIN_THICKNESS", min_thickness, & 'Minimum thickness for layer',& - units='m', default=1.0e-3, do_not_log=.true., scale=US%m_to_Z) + units='m', default=1.0e-3, scale=US%m_to_Z, do_not_log=.true.) ! no active sponges if (sponge_time_scale <= 0.) return diff --git a/src/user/seamount_initialization.F90 b/src/user/seamount_initialization.F90 index dfd39e328f..5b62993551 100644 --- a/src/user/seamount_initialization.F90 +++ b/src/user/seamount_initialization.F90 @@ -93,7 +93,8 @@ subroutine seamount_initialize_thickness (h, depth_tot, G, GV, US, param_file, j ! negative because it is positive upward. real :: eta1D(SZK_(GV)+1) ! Interface height relative to the sea surface, positive upward [Z ~> m] real :: min_thickness ! The minimum layer thicknesses [Z ~> m]. - real :: S_surf, S_range, S_ref, S_light, S_dense ! Various salinities [ppt]. + real :: S_ref ! A default value for salinities [ppt]. + real :: S_surf, S_range, S_light, S_dense ! Various salinities [S ~> ppt]. real :: eta_IC_quanta ! The granularity of quantization of intial interface heights [Z-1 ~> m-1]. character(len=20) :: verticalCoordinate integer :: i, j, k, is, ie, js, je, nz @@ -123,11 +124,15 @@ subroutine seamount_initialize_thickness (h, depth_tot, G, GV, US, param_file, j select case ( coordinateMode(verticalCoordinate) ) case ( REGRIDDING_LAYER, REGRIDDING_RHO ) ! Initial thicknesses for isopycnal coordinates - call get_param(param_file, mdl,"INITIAL_SSS", S_surf, default=34., do_not_log=.true.) - call get_param(param_file, mdl,"INITIAL_S_RANGE", S_range, default=2., do_not_log=.true.) + call get_param(param_file, mdl,"INITIAL_SSS", S_surf, & + units="ppt", default=34., scale=US%ppt_to_S, do_not_log=.true.) + call get_param(param_file, mdl,"INITIAL_S_RANGE", S_range, & + units="ppt", default=2., scale=US%ppt_to_S, do_not_log=.true.) call get_param(param_file, mdl, "S_REF", S_ref, default=35.0, do_not_log=.true.) - call get_param(param_file, mdl, "TS_RANGE_S_LIGHT", S_light, default = S_Ref, do_not_log=.true.) - call get_param(param_file, mdl, "TS_RANGE_S_DENSE", S_dense, default = S_Ref, do_not_log=.true.) + call get_param(param_file, mdl, "TS_RANGE_S_LIGHT", S_light, & + units="ppt", default=S_Ref, scale=US%ppt_to_S, do_not_log=.true.) + call get_param(param_file, mdl, "TS_RANGE_S_DENSE", S_dense, & + units="ppt", default=S_Ref, scale=US%ppt_to_S, do_not_log=.true.) call get_param(param_file, mdl, "INTERFACE_IC_QUANTA", eta_IC_quanta, & "The granularity of initial interface height values "//& "per meter, to avoid sensivity to order-of-arithmetic changes.", & @@ -188,12 +193,13 @@ subroutine seamount_initialize_thickness (h, depth_tot, G, GV, US, param_file, j end subroutine seamount_initialize_thickness !> Initial values for temperature and salinity -subroutine seamount_initialize_temperature_salinity(T, S, h, G, GV, param_file, just_read) +subroutine seamount_initialize_temperature_salinity(T, S, h, G, GV, US, param_file, just_read) type(ocean_grid_type), intent(in) :: G !< Ocean grid structure type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [degC] - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [ppt] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [C ~> degC] + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [S ~> ppt] real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2] + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< Parameter file structure logical, intent(in) :: just_read !< If true, this call will !! only read parameters without changing T & S. @@ -212,25 +218,31 @@ subroutine seamount_initialize_temperature_salinity(T, S, h, G, GV, param_file, 'Initial profile shape. Valid values are "linear", "parabolic" '//& 'and "exponential".', default='linear', do_not_log=just_read) call get_param(param_file, mdl,"INITIAL_SSS", S_surf, & - 'Initial surface salinity', units='1e-3', default=34., do_not_log=just_read) + 'Initial surface salinity', & + units='1e-3', default=34., scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl,"INITIAL_SST", T_surf, & - 'Initial surface temperature', units='C', default=0., do_not_log=just_read) + 'Initial surface temperature', & + units='C', default=0., scale=US%degC_to_C, do_not_log=just_read) call get_param(param_file, mdl,"INITIAL_S_RANGE", S_range, & - 'Initial salinity range (bottom - surface)', units='1e-3', & - default=2., do_not_log=just_read) + 'Initial salinity range (bottom - surface)', & + units='1e-3', default=2., scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl,"INITIAL_T_RANGE", T_range, & - 'Initial temperature range (bottom - surface)', units='C', & - default=0., do_not_log=just_read) + 'Initial temperature range (bottom - surface)', & + units='C', default=0., scale=US%degC_to_C, do_not_log=just_read) select case ( coordinateMode(verticalCoordinate) ) case ( REGRIDDING_LAYER ) ! Initial thicknesses for layer isopycnal coordinates ! These parameters are used in MOM_fixed_initialization.F90 when CONFIG_COORD="ts_range" call get_param(param_file, mdl, "T_REF", T_ref, default=10.0, do_not_log=.true.) - call get_param(param_file, mdl, "TS_RANGE_T_LIGHT", T_light, default=T_Ref, do_not_log=.true.) - call get_param(param_file, mdl, "TS_RANGE_T_DENSE", T_dense, default=T_Ref, do_not_log=.true.) + call get_param(param_file, mdl, "TS_RANGE_T_LIGHT", T_light, & + default=T_Ref, scale=US%degC_to_C, do_not_log=.true.) + call get_param(param_file, mdl, "TS_RANGE_T_DENSE", T_dense, & + default=T_Ref, scale=US%degC_to_C, do_not_log=.true.) call get_param(param_file, mdl, "S_REF", S_ref, default=35.0, do_not_log=.true.) - call get_param(param_file, mdl, "TS_RANGE_S_LIGHT", S_light, default = S_Ref, do_not_log=.true.) - call get_param(param_file, mdl, "TS_RANGE_S_DENSE", S_dense, default = S_Ref, do_not_log=.true.) + call get_param(param_file, mdl, "TS_RANGE_S_LIGHT", S_light, & + default = S_Ref, scale=US%ppt_to_S, do_not_log=.true.) + call get_param(param_file, mdl, "TS_RANGE_S_DENSE", S_dense, & + default = S_Ref, scale=US%ppt_to_S, do_not_log=.true.) call get_param(param_file, mdl, "TS_RANGE_RESOLN_RATIO", res_rat, default=1.0, do_not_log=.true.) if (just_read) return ! All run-time parameters have been read, so return. diff --git a/src/user/sloshing_initialization.F90 b/src/user/sloshing_initialization.F90 index 641afa5f3e..de7869511b 100644 --- a/src/user/sloshing_initialization.F90 +++ b/src/user/sloshing_initialization.F90 @@ -175,12 +175,13 @@ end subroutine sloshing_initialize_thickness !! reference surface layer salinity and temperature and a specified range. !! Note that the linear distribution is set up with respect to the layer !! number, not the physical position). -subroutine sloshing_initialize_temperature_salinity ( T, S, h, G, GV, param_file, just_read) +subroutine sloshing_initialize_temperature_salinity ( T, S, h, G, GV, US, param_file, just_read) type(ocean_grid_type), intent(in) :: G !< Ocean grid structure. type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure. - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [degC]. - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [ppt]. + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [C ~> degC]. + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [S ~> ppt]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2]. + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type type(param_file_type), intent(in) :: param_file !< A structure indicating the !! open file to parse for model !! parameter values. @@ -189,9 +190,9 @@ subroutine sloshing_initialize_temperature_salinity ( T, S, h, G, GV, param_file integer :: i, j, k, is, ie, js, je, nz real :: delta_T - real :: S_ref, T_ref; ! Reference salinity and temerature within + real :: S_ref, T_ref; ! Reference salinity [S ~> ppt] and temperature [C ~> degC] within ! surface layer - real :: S_range, T_range; ! Range of salinities and temperatures over the + real :: S_range, T_range; ! Range of [S ~> ppt] and temperatures [C ~> degC] over the ! vertical integer :: kdelta real :: deltah @@ -202,15 +203,15 @@ subroutine sloshing_initialize_temperature_salinity ( T, S, h, G, GV, param_file is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke call get_param(param_file, mdl, "S_REF", S_ref, 'Reference value for salinity', & - default=35.0, units='1e-3', do_not_log=just_read) + default=35.0, units='1e-3', scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl, "T_REF", T_ref, 'Reference value for temperature', & - units='degC', fail_if_missing=.not.just_read, do_not_log=just_read) + units='degC', scale=US%degC_to_C, fail_if_missing=.not.just_read, do_not_log=just_read) ! The default is to assume an increase by 2 ppt for the salinity and a uniform temperature. call get_param(param_file, mdl,"S_RANGE",S_range,'Initial salinity range.', & - units='1e-3', default=2.0, do_not_log=just_read) + units='1e-3', default=2.0, scale=US%ppt_to_S, do_not_log=just_read) call get_param(param_file, mdl,"T_RANGE",T_range,'Initial temperature range', & - units='degC', default=0.0, do_not_log=just_read) + units='degC', default=0.0, scale=US%degC_to_C, do_not_log=just_read) if (just_read) return ! All run-time parameters have been read, so return. @@ -227,7 +228,7 @@ subroutine sloshing_initialize_temperature_salinity ( T, S, h, G, GV, param_file xi0 = 0.0 do k = 1,nz xi1 = xi0 + deltah / G%max_depth ! = xi0 + 1.0 / real(nz) - S(i,j,k) = 34.0 + 0.5 * S_range * (xi0 + xi1) + S(i,j,k) = 34.0*US%ppt_to_S + 0.5 * S_range * (xi0 + xi1) xi0 = xi1 enddo enddo ; enddo @@ -240,7 +241,7 @@ subroutine sloshing_initialize_temperature_salinity ( T, S, h, G, GV, param_file T(:,:,k) = T(:,:,k-1) + delta_T enddo kdelta = 2 - T(:,:,GV%ke/2 - (kdelta-1):GV%ke/2 + kdelta) = 1.0 + T(:,:,GV%ke/2 - (kdelta-1):GV%ke/2 + kdelta) = 1.0*US%degC_to_C end subroutine sloshing_initialize_temperature_salinity diff --git a/src/user/user_change_diffusivity.F90 b/src/user/user_change_diffusivity.F90 index f0ed674cf9..762cee5446 100644 --- a/src/user/user_change_diffusivity.F90 +++ b/src/user/user_change_diffusivity.F90 @@ -59,9 +59,9 @@ subroutine user_change_diff(h, tv, G, GV, US, CS, Kd_lay, Kd_int, T_f, S_f, Kd_i real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1), optional, intent(inout) :: Kd_int !< The diapycnal diffusivity !! at each interface [Z2 T-1 ~> m2 s-1]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), optional, intent(in) :: T_f !< Temperature with massless - !! layers filled in vertically [degC]. + !! layers filled in vertically [C ~> degC]. real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), optional, intent(in) :: S_f !< Salinity with massless - !! layers filled in vertically [ppt]. + !! layers filled in vertically [S ~> ppt]. real, dimension(:,:,:), optional, pointer :: Kd_int_add !< The diapycnal !! diffusivity that is being added at !! each interface [Z2 T-1 ~> m2 s-1]. diff --git a/src/user/user_initialization.F90 b/src/user/user_initialization.F90 index e115cd8f30..b9d16e548a 100644 --- a/src/user/user_initialization.F90 +++ b/src/user/user_initialization.F90 @@ -130,8 +130,8 @@ end subroutine USER_initialize_velocity subroutine USER_init_temperature_salinity(T, S, G, GV, param_file, just_read) type(ocean_grid_type), intent(in) :: G !< Ocean grid structure. type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure. - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [degC]. - real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [ppt]. + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: T !< Potential temperature [C ~> degC]. + real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(out) :: S !< Salinity [S ~> ppt]. type(param_file_type), intent(in) :: param_file !< A structure indicating the !! open file to parse for model !! parameter values. @@ -238,8 +238,8 @@ end subroutine write_user_log !! - GV%g_prime - The reduced gravity at each interface [L2 Z-1 T-2 ~> m s-2]. !! - GV%Rlay - Layer potential density (coordinate variable) [R ~> kg m-3]. !! If ENABLE_THERMODYNAMICS is defined: -!! - T - Temperature [degC]. -!! - S - Salinity [ppt]. +!! - T - Temperature [C ~> degC]. +!! - S - Salinity [S ~> ppt]. !! If BULKMIXEDLAYER is defined: !! - Rml - Mixed layer and buffer layer potential densities [R ~> kg m-3]. !! If SPONGE is defined: