From 8e833d4d93476d38002bff7836f937a69b482bdb Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Thu, 9 Jun 2022 14:49:26 -0600 Subject: [PATCH 01/27] Add missing units Address comment from reviewer by adding units to covTS and varS. --- src/parameterizations/lateral/MOM_mixed_layer_restrat.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/parameterizations/lateral/MOM_mixed_layer_restrat.F90 b/src/parameterizations/lateral/MOM_mixed_layer_restrat.F90 index 0c223ffdeb..864669a217 100644 --- a/src/parameterizations/lateral/MOM_mixed_layer_restrat.F90 +++ b/src/parameterizations/lateral/MOM_mixed_layer_restrat.F90 @@ -179,7 +179,8 @@ subroutine mixedlayer_restrat_general(h, uhtr, vhtr, tv, forces, dt, MLD_in, Var real, dimension(SZI_(G)) :: dK, dKm1 ! Depths of layer centers [H ~> m or kg m-2]. real, dimension(SZI_(G)) :: pRef_MLD ! A reference pressure for calculating the mixed layer ! densities [R L2 T-2 ~> Pa]. - real, dimension(SZI_(G)) :: covTS, varS !SGS TS covariance, S variance in Stanley param; currently 0 + real, dimension(SZI_(G)) :: covTS, & !SGS TS covariance in Stanley param; currently 0 [degC ppt] + varS !SGS S variance in Stanley param; currently 0 [ppt2] real :: aFac, bFac ! Nondimensional ratios [nondim] real :: ddRho ! A density difference [R ~> kg m-3] real :: hAtVel ! Thickness at the velocity points [H ~> m or kg m-2] From 6057714230bed75fd3093a6b73d60c478e42c9ac Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Thu, 9 Jun 2022 14:51:44 -0600 Subject: [PATCH 02/27] Follow MOM6 code style guide * Add ``implicit none ; private`` to this module; * Put module variables into the control structure for this module; * Add the description of the units for all real variables; * Add a consistent two-point indent throughout the module . TODO: Without further modifications, adding ``private`` to the control structure of this module will break the model. Currently, MOM.F90 needs access to ``use_stoch_eos``, ``stanley_coeff``, and some of the diagnostic ids. --- src/core/MOM_stoch_eos.F90 | 234 +++++++++++++++++++------------------ 1 file changed, 121 insertions(+), 113 deletions(-) diff --git a/src/core/MOM_stoch_eos.F90 b/src/core/MOM_stoch_eos.F90 index 0ee6d6b1be..bc5e15af4e 100644 --- a/src/core/MOM_stoch_eos.F90 +++ b/src/core/MOM_stoch_eos.F90 @@ -1,5 +1,6 @@ !> Provides the ocean stochastic equation of state module MOM_stoch_eos + ! This file is part of MOM6. See LICENSE.md for the license. use MOM_grid, only : ocean_grid_type use MOM_hor_index, only : hor_index_type @@ -15,148 +16,156 @@ module MOM_stoch_eos use MOM_isopycnal_slopes,only : vert_fill_TS !use random_numbers_mod, only : getRandomNumbers,initializeRandomNumberStream,randomNumberStream -implicit none +implicit none; private #include public MOM_stoch_eos_init public MOM_stoch_eos_run public MOM_calc_varT -real,private ALLOCABLE_, dimension(NIMEM_,NJMEM_) :: l2_inv - !< One over sum of the T cell side side lengths squared -real,private ALLOCABLE_, dimension(NIMEM_,NJMEM_) :: rgauss !< nondimensional random Gaussian -real, parameter,private :: tfac=0.27 !< Nondimensional decorrelation time factor, ~1/3.7 -real, parameter,private :: amplitude=0.624499 !< Nondimensional std dev of Gaussian -integer ,private :: seed !< PRNG seed -type(PRNG) :: rn_CS !< PRNG control structure - !> Describes parameters of the stochastic component of the EOS !! correction, described in Stanley et al. JAMES 2020. type, public :: MOM_stoch_eos_CS - real,public ALLOCABLE_, dimension(NIMEM_,NJMEM_) :: pattern - !< Random pattern for stochastic EOS + real ALLOCABLE_, dimension(NIMEM_,NJMEM_) :: l2_inv + !< One over sum of the T cell side side lengths squared + real ALLOCABLE_, dimension(NIMEM_,NJMEM_) :: rgauss + !< nondimensional random Gaussian + real :: tfac=0.27 !< Nondimensional decorrelation time factor, ~1/3.7 + real :: amplitude=0.624499 !< Nondimensional std dev of Gaussian + integer :: seed !< PRNG seed + type(PRNG) :: rn_CS !< PRNG control structure + real ALLOCABLE_, dimension(NIMEM_,NJMEM_) :: pattern + !< Random pattern for stochastic EOS [nondim] real ALLOCABLE_, dimension(NIMEM_,NJMEM_) :: phi - !< temporal correlation stochastic EOS (deugging) - logical :: use_stoch_eos !< If true, use the stochastic equation of state (Stanley et al. 2020) - real :: stanley_coeff !< Coefficient correlating the temperature gradient - !and SGS T variance; if <0, turn off scheme in all codes - real :: stanley_a ! m2 s-1] + !>@{ Diagnostic IDs integer :: id_stoch_eos = -1, id_stoch_phi = -1, id_tvar_sgs = -1 !>@} end type MOM_stoch_eos_CS - contains - subroutine MOM_stoch_eos_init(G,Time,param_file,stoch_eos_CS,restart_CS,diag) -! initialization subroutine called by MOM.F90, - type(param_file_type), intent(in) :: param_file !< structure indicating parameter file to parse - type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure. - type(time_type), intent(in) :: Time !< Time for stochastic process - type(MOM_stoch_eos_CS), intent(inout) :: stoch_eos_CS !< Stochastic control structure - type(MOM_restart_CS), pointer :: restart_CS !< A pointer to the restart control structure. - type(diag_ctrl), target, intent(inout) :: diag !< to control diagnostics + +!> Initializes MOM_stoch_eos module. +subroutine MOM_stoch_eos_init(G,Time,param_file,CS,restart_CS,diag) + type(param_file_type), intent(in) :: param_file !< structure indicating parameter file to parse + type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure. + type(time_type), intent(in) :: Time !< Time for stochastic process + type(MOM_stoch_eos_CS), intent(inout) :: CS !< Stochastic control structure + type(MOM_restart_CS), pointer :: restart_CS !< A pointer to the restart control structure. + type(diag_ctrl), target, intent(inout) :: diag !< to control diagnostics + + ! local variables integer :: i,j - type(vardesc) :: vd - seed=0 + type(vardesc) :: vd + CS%seed=0 ! contants !pi=2*acos(0.0) - call get_param(param_file, "MOM_stoch_eos", "STOCH_EOS", stoch_eos_CS%use_stoch_eos, & + call get_param(param_file, "MOM_stoch_eos", "STOCH_EOS", CS%use_stoch_eos, & "If true, stochastic perturbations are applied "//& "to the EOS in the PGF.", default=.false.) - call get_param(param_file, "MOM_stoch_eos", "STANLEY_COEFF", stoch_eos_CS%stanley_coeff, & + call get_param(param_file, "MOM_stoch_eos", "STANLEY_COEFF", CS%stanley_coeff, & "Coefficient correlating the temperature gradient "//& "and SGS T variance.", default=-1.0) - call get_param(param_file, "MOM_stoch_eos", "STANLEY_A", stoch_eos_CS%stanley_a, & + call get_param(param_file, "MOM_stoch_eos", "STANLEY_A", CS%stanley_a, & "Coefficient a which scales chi in stochastic perturbation of the "//& "SGS T variance.", default=1.0) - call get_param(param_file, "MOM_stoch_eos", "KD_SMOOTH", stoch_eos_CS%kappa_smooth, & + call get_param(param_file, "MOM_stoch_eos", "KD_SMOOTH", CS%kappa_smooth, & "A diapycnal diffusivity that is used to interpolate "//& "more sensible values of T & S into thin layers.", & units="m2 s-1", default=1.0e-6) !don't run anything if STANLEY_COEFF < 0 - if (stoch_eos_CS%stanley_coeff >= 0.0) then + if (CS%stanley_coeff >= 0.0) then - ALLOC_(stoch_eos_CS%pattern(G%isd:G%ied,G%jsd:G%jed)) ; stoch_eos_CS%pattern(:,:) = 0.0 + ALLOC_(CS%pattern(G%isd:G%ied,G%jsd:G%jed)) ; CS%pattern(:,:) = 0.0 vd = var_desc("stoch_eos_pattern","nondim","Random pattern for stoch EOS",'h','1') - call register_restart_field(stoch_eos_CS%pattern, vd, .false., restart_CS) - ALLOC_(stoch_eos_CS%phi(G%isd:G%ied,G%jsd:G%jed)) ; stoch_eos_CS%phi(:,:) = 0.0 - ALLOC_(l2_inv(G%isd:G%ied,G%jsd:G%jed)) - ALLOC_(rgauss(G%isd:G%ied,G%jsd:G%jed)) - call get_param(param_file, "MOM_stoch_eos", "SEED_STOCH_EOS", seed, & + call register_restart_field(CS%pattern, vd, .false., restart_CS) + ALLOC_(CS%phi(G%isd:G%ied,G%jsd:G%jed)) ; CS%phi(:,:) = 0.0 + ALLOC_(CS%l2_inv(G%isd:G%ied,G%jsd:G%jed)) + ALLOC_(CS%rgauss(G%isd:G%ied,G%jsd:G%jed)) + call get_param(param_file, "MOM_stoch_eos", "SEED_STOCH_EOS", CS%seed, & "Specfied seed for random number sequence ", default=0) - call random_2d_constructor(rn_CS, G%HI, Time, seed) - call random_2d_norm(rn_CS, G%HI, rgauss) + call random_2d_constructor(CS%rn_CS, G%HI, Time, CS%seed) + call random_2d_norm(CS%rn_CS, G%HI, CS%rgauss) ! fill array with approximation of grid area needed for decorrelation ! time-scale calculation do j=G%jsc,G%jec - do i=G%isc,G%iec - l2_inv(i,j)=1.0/(G%dxT(i,j)**2+G%dyT(i,j)**2) - enddo + do i=G%isc,G%iec + CS%l2_inv(i,j)=1.0/(G%dxT(i,j)**2+G%dyT(i,j)**2) + enddo enddo if (is_new_run(restart_CS)) then - do j=G%jsc,G%jec - do i=G%isc,G%iec - stoch_eos_CS%pattern(i,j)=amplitude*rgauss(i,j) - enddo - enddo + do j=G%jsc,G%jec + do i=G%isc,G%iec + CS%pattern(i,j)=CS%amplitude*CS%rgauss(i,j) + enddo + enddo endif !register diagnostics - stoch_eos_CS%id_tvar_sgs = register_diag_field('ocean_model', 'tvar_sgs', diag%axesTL, Time, & + CS%id_tvar_sgs = register_diag_field('ocean_model', 'tvar_sgs', diag%axesTL, Time, & 'Parameterized SGS Temperature Variance ', 'None') - if (stoch_eos_CS%use_stoch_eos) then - stoch_eos_CS%id_stoch_eos = register_diag_field('ocean_model', 'stoch_eos', diag%axesT1, Time, & + if (CS%use_stoch_eos) then + CS%id_stoch_eos = register_diag_field('ocean_model', 'stoch_eos', diag%axesT1, Time, & 'random pattern for EOS', 'None') - stoch_eos_CS%id_stoch_phi = register_diag_field('ocean_model', 'stoch_phi', diag%axesT1, Time, & + CS%id_stoch_phi = register_diag_field('ocean_model', 'stoch_phi', diag%axesT1, Time, & 'phi for EOS', 'None') endif endif - end subroutine MOM_stoch_eos_init +end subroutine MOM_stoch_eos_init - subroutine MOM_stoch_eos_run(G,u,v,delt,Time,stoch_eos_CS,diag) - type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure. +!> Generates a pattern in space and time for the ocean stochastic equation of state +subroutine MOM_stoch_eos_run(G,u,v,delt,Time,CS,diag) + type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure. real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), & - intent(in) :: u !< The zonal velocity [L T-1 ~> m s-1]. + intent(in) :: u !< The zonal velocity [L T-1 ~> m s-1]. real, dimension(SZI_(G),SZJB_(G),SZK_(G)), & - intent(in) :: v !< The meridional velocity [L T-1 ~> m s-1]. - real, intent(in) :: delt !< Time step size for AR1 process [T ~> s]. - type(time_type), intent(in) :: Time !< Time for stochastic process - type(MOM_stoch_eos_CS), intent(inout) :: stoch_eos_CS !< Stochastic control structure - type(diag_ctrl), target, intent(inout) :: diag !< to control diagnostics -! locals - integer :: i,j + intent(in) :: v !< The meridional velocity [L T-1 ~> m s-1]. + real, intent(in) :: delt !< Time step size for AR1 process [T ~> s]. + type(time_type), intent(in) :: Time !< Time for stochastic process + type(MOM_stoch_eos_CS), intent(inout) :: CS !< Stochastic control structure + type(diag_ctrl), target, intent(inout) :: diag !< to control diagnostics + + ! local variables + integer :: i,j integer :: yr,mo,dy,hr,mn,sc - real :: phi,ubar,vbar + real :: phi,ubar,vbar + + call random_2d_constructor(CS%rn_CS, G%HI, Time, CS%seed) + call random_2d_norm(CS%rn_CS, G%HI, CS%rgauss) - call random_2d_constructor(rn_CS, G%HI, Time, seed) - call random_2d_norm(rn_CS, G%HI, rgauss) ! advance AR(1) do j=G%jsc,G%jec - do i=G%isc,G%iec - ubar=0.5*(u(I,j,1)*G%mask2dCu(I,j)+u(I-1,j,1)*G%mask2dCu(I-1,j)) - vbar=0.5*(v(i,J,1)*G%mask2dCv(i,J)+v(i,J-1,1)*G%mask2dCv(i,J-1)) - phi=exp(-delt*tfac*sqrt((ubar**2+vbar**2)*l2_inv(i,j))) - stoch_eos_CS%pattern(i,j)=phi*stoch_eos_CS%pattern(i,j) + amplitude*sqrt(1-phi**2)*rgauss(i,j) - stoch_eos_CS%phi(i,j)=phi - enddo + do i=G%isc,G%iec + ubar=0.5*(u(I,j,1)*G%mask2dCu(I,j)+u(I-1,j,1)*G%mask2dCu(I-1,j)) + vbar=0.5*(v(i,J,1)*G%mask2dCv(i,J)+v(i,J-1,1)*G%mask2dCv(i,J-1)) + phi=exp(-delt*CS%tfac*sqrt((ubar**2+vbar**2)*CS%l2_inv(i,j))) + CS%pattern(i,j)=phi*CS%pattern(i,j) + CS%amplitude*sqrt(1-phi**2)*CS%rgauss(i,j) + CS%phi(i,j)=phi + enddo enddo - end subroutine MOM_stoch_eos_run +end subroutine MOM_stoch_eos_run +!> Computes a parameterization of the SGS temperature variance +subroutine MOM_calc_varT(G,GV,h,tv,CS,dt) + type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure. + type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure + real, dimension(SZI_(G),SZJ_(G),SZK_(G)), & + intent(in) :: h !< Layer thickness [H ~> m] + type(thermo_var_ptrs), intent(inout) :: tv !< Thermodynamics structure + type(MOM_stoch_eos_CS), intent(inout) :: CS !< Stochastic control structure + real, intent(in) :: dt !< Time increment [T ~> s] - subroutine MOM_calc_varT(G,GV,h,tv,stoch_eos_CS,dt) - type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure. - type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure - real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thickness [H ~> m] - type(thermo_var_ptrs), intent(inout) :: tv !< Thermodynamics structure - type(MOM_stoch_eos_CS), intent(inout) :: stoch_eos_CS !< Stochastic control structure. - real, intent(in) :: dt !< Time increment [T ~> s] -! locals + ! local variables real, dimension(SZI_(G), SZJ_(G), SZK_(GV)) :: & T, & !> The temperature (or density) [degC], with the values in !! in massless layers filled vertically by diffusion. @@ -171,42 +180,41 @@ subroutine MOM_calc_varT(G,GV,h,tv,stoch_eos_CS,dt) ! still a poor approximation in the interior when coordinates are strongly tilted. if (.not. associated(tv%varT)) call safe_alloc_ptr(tv%varT, G%isd, G%ied, G%jsd, G%jed, GV%ke) - call vert_fill_TS(h, tv%T, tv%S, stoch_eos_CS%kappa_smooth*dt, T, S, G, GV, halo_here=1, larger_h_denom=.true.) + call vert_fill_TS(h, tv%T, tv%S, CS%kappa_smooth*dt, T, S, G, GV, halo_here=1, larger_h_denom=.true.) do k=1,G%ke - do j=G%jsc,G%jec - do i=G%isc,G%iec - hl(1) = h(i,j,k) * G%mask2dT(i,j) - hl(2) = h(i-1,j,k) * G%mask2dCu(I-1,j) - hl(3) = h(i+1,j,k) * G%mask2dCu(I,j) - hl(4) = h(i,j-1,k) * G%mask2dCv(i,J-1) - hl(5) = h(i,j+1,k) * G%mask2dCv(i,J) - - ! SGS variance in i-direction [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] - 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 - tv%varT(i,j,k) = stoch_eos_CS%stanley_coeff * ( dTdi2 + dTdj2 ) - ! Turn off scheme near land - tv%varT(i,j,k) = tv%varT(i,j,k) * (minval(hl) / (maxval(hl) + GV%H_subroundoff)) - enddo - enddo + do j=G%jsc,G%jec + do i=G%isc,G%iec + hl(1) = h(i,j,k) * G%mask2dT(i,j) + hl(2) = h(i-1,j,k) * G%mask2dCu(I-1,j) + hl(3) = h(i+1,j,k) * G%mask2dCu(I,j) + hl(4) = h(i,j-1,k) * G%mask2dCv(i,J-1) + hl(5) = h(i,j+1,k) * G%mask2dCv(i,J) + + ! SGS variance in i-direction [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] + 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 + tv%varT(i,j,k) = CS%stanley_coeff * ( dTdi2 + dTdj2 ) + ! Turn off scheme near land + tv%varT(i,j,k) = tv%varT(i,j,k) * (minval(hl) / (maxval(hl) + GV%H_subroundoff)) + enddo + enddo enddo ! if stochastic, perturb - if (stoch_eos_CS%use_stoch_eos) then - do k=1,G%ke - do j=G%jsc,G%jec - do i=G%isc,G%iec - tv%varT(i,j,k) = exp (stoch_eos_CS%stanley_a * stoch_eos_CS%pattern(i,j)) * tv%varT(i,j,k) - enddo + if (CS%use_stoch_eos) then + do k=1,G%ke + do j=G%jsc,G%jec + do i=G%isc,G%iec + tv%varT(i,j,k) = exp (CS%stanley_a * CS%pattern(i,j)) * tv%varT(i,j,k) enddo - enddo + enddo + enddo endif - end subroutine MOM_calc_varT +end subroutine MOM_calc_varT end module MOM_stoch_eos - From bb02a51becfbfbb9d7d46332fb6f4c77015e0881 Mon Sep 17 00:00:00 2001 From: Scott Bachman Date: Fri, 29 Jul 2022 11:41:20 -0600 Subject: [PATCH 03/27] A new tracer that keeps track of "mixed layer age" has been added to the ideal age module. This PR also adds the ability to use the actual BL depth that is diagnosed by the active BL scheme inside the ideal age module (for all ideal age tracers). --- src/tracer/MOM_tracer_flow_control.F90 | 5 +- src/tracer/ideal_age_example.F90 | 227 +++++++++++++++++++++---- 2 files changed, 199 insertions(+), 33 deletions(-) diff --git a/src/tracer/MOM_tracer_flow_control.F90 b/src/tracer/MOM_tracer_flow_control.F90 index d1c105fcd5..3dac584571 100644 --- a/src/tracer/MOM_tracer_flow_control.F90 +++ b/src/tracer/MOM_tracer_flow_control.F90 @@ -468,7 +468,8 @@ subroutine call_tracer_column_fns(h_old, h_new, ea, eb, fluxes, Hml, dt, G, GV, call ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & G, GV, US, CS%ideal_age_tracer_CSp, & evap_CFL_limit=evap_CFL_limit, & - minimum_forcing_depth=minimum_forcing_depth) + minimum_forcing_depth=minimum_forcing_depth, & + Hml=Hml) if (CS%use_regional_dyes) & call dye_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & G, GV, US, CS%dye_tracer_CSp, & @@ -544,7 +545,7 @@ subroutine call_tracer_column_fns(h_old, h_new, ea, eb, fluxes, Hml, dt, G, GV, G, GV, US, CS%RGC_tracer_CSp) if (CS%use_ideal_age) & call ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & - G, GV, US, CS%ideal_age_tracer_CSp) + G, GV, US, CS%ideal_age_tracer_CSp, Hml=Hml) if (CS%use_regional_dyes) & call dye_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & G, GV, US, CS%dye_tracer_CSp) diff --git a/src/tracer/ideal_age_example.F90 b/src/tracer/ideal_age_example.F90 index 2fdeaff02f..92aab231a2 100644 --- a/src/tracer/ideal_age_example.F90 +++ b/src/tracer/ideal_age_example.F90 @@ -6,7 +6,7 @@ module ideal_age_example use MOM_coms, only : EFP_type use MOM_coupler_types, only : set_coupler_type_data, atmos_ocn_coupler_flux use MOM_diag_mediator, only : diag_ctrl -use MOM_error_handler, only : MOM_error, FATAL, WARNING +use MOM_error_handler, only : MOM_error, FATAL, WARNING, NOTE use MOM_file_parser, only : get_param, log_param, log_version, param_file_type use MOM_forcing_type, only : forcing use MOM_grid, only : ocean_grid_type @@ -31,8 +31,9 @@ module ideal_age_example public register_ideal_age_tracer, initialize_ideal_age_tracer public ideal_age_tracer_column_physics, ideal_age_tracer_surface_state public ideal_age_stock, ideal_age_example_end +public count_ML_layers -integer, parameter :: NTR_MAX = 3 !< the maximum number of tracers in this module. +integer, parameter :: NTR_MAX = 4 !< the maximum number of tracers in this module. !> The control structure for the ideal_age_tracer package type, public :: ideal_age_tracer_CS ; private @@ -49,9 +50,12 @@ module ideal_age_example real, dimension(NTR_MAX) :: IC_val = 0.0 !< The (uniform) initial condition value. real, dimension(NTR_MAX) :: young_val = 0.0 !< The value assigned to tr at the surface. real, dimension(NTR_MAX) :: land_val = -1.0 !< The value of tr used where land is masked out. - real, dimension(NTR_MAX) :: sfc_growth_rate !< The exponential growth rate for the surface value [year-1]. + real, dimension(NTR_MAX) :: growth_rate !< The exponential growth rate for the young value [year-1]. real, dimension(NTR_MAX) :: tracer_start_year !< The year in which tracers start aging, or at which the !! surface value equals young_val, in years. + logical :: use_real_BL_depth !< If true, uses the BL scheme to determine the number of + !! layers above the BL depth instead of the fixed nkml value. + integer :: ML_residence_num !! The tracer number assigned to the ML residence tracer in this module logical :: tracers_may_reinit !< If true, these tracers be set up via the initialization code if !! they are not found in the restart files. logical :: tracer_ages(NTR_MAX) !< Indicates whether each tracer ages. @@ -64,6 +68,7 @@ module ideal_age_example type(MOM_restart_CS), pointer :: restart_CSp => NULL() !< A pointer to the restart controls structure type(vardesc) :: tr_desc(NTR_MAX) !< Descriptions and metadata for the tracers + end type ideal_age_tracer_CS contains @@ -87,7 +92,7 @@ function register_ideal_age_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS) character(len=48) :: var_name ! The variable's name. real, pointer :: tr_ptr(:,:,:) => NULL() logical :: register_ideal_age_tracer - logical :: do_ideal_age, do_vintage, do_ideal_age_dated + logical :: do_ideal_age, do_vintage, do_ideal_age_dated, do_ML_residence integer :: isd, ied, jsd, jed, nz, m isd = HI%isd ; ied = HI%ied ; jsd = HI%jsd ; jed = HI%jed ; nz = GV%ke @@ -114,8 +119,14 @@ function register_ideal_age_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS) "the standard ideal age tracer - i.e. is set to 0 age in "//& "the mixed layer and ages at unit rate in the interior.", & default=.false.) - - + call get_param(param_file, mdl, "DO_ML_RESIDENCE", do_ML_residence, & + "If true, use a residence tracer that is set to 0 age "//& + "in the interior and ages at unit rate in the mixed layer.", & + default=.false.) + call get_param(param_file, mdl, "USE_REAL_BL_DEPTH", CS%use_real_BL_depth, & + "If true, the ideal age tracers will use the boundary layer "//& + "depth diagnosed from the BL or bulkmixedlayer scheme.", & + default=.false.) call get_param(param_file, mdl, "AGE_IC_FILE", CS%IC_file, & "The file in which the age-tracer initial values can be "//& "found, or an empty string for internal initialization.", & @@ -139,7 +150,7 @@ function register_ideal_age_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS) if (do_ideal_age) then CS%ntr = CS%ntr + 1 ; m = CS%ntr CS%tr_desc(m) = var_desc("age", "yr", "Ideal Age Tracer", cmor_field_name="agessc", caller=mdl) - CS%tracer_ages(m) = .true. ; CS%sfc_growth_rate(m) = 0.0 + CS%tracer_ages(m) = .true. ; CS%growth_rate(m) = 0.0 CS%IC_val(m) = 0.0 ; CS%young_val(m) = 0.0 ; CS%tracer_start_year(m) = 0.0 endif @@ -147,7 +158,7 @@ function register_ideal_age_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS) CS%ntr = CS%ntr + 1 ; m = CS%ntr CS%tr_desc(m) = var_desc("vintage", "yr", "Exponential Vintage Tracer", & caller=mdl) - CS%tracer_ages(m) = .false. ; CS%sfc_growth_rate(m) = 1.0/30.0 + CS%tracer_ages(m) = .false. ; CS%growth_rate(m) = 1.0/30.0 CS%IC_val(m) = 0.0 ; CS%young_val(m) = 1e-20 ; CS%tracer_start_year(m) = 0.0 call get_param(param_file, mdl, "IDEAL_VINTAGE_START_YEAR", CS%tracer_start_year(m), & "The date at which the ideal vintage tracer starts.", & @@ -158,13 +169,21 @@ function register_ideal_age_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS) CS%ntr = CS%ntr + 1 ; m = CS%ntr CS%tr_desc(m) = var_desc("age_dated","yr","Ideal Age Tracer with a Start Date",& caller=mdl) - CS%tracer_ages(m) = .true. ; CS%sfc_growth_rate(m) = 0.0 + CS%tracer_ages(m) = .true. ; CS%growth_rate(m) = 0.0 CS%IC_val(m) = 0.0 ; CS%young_val(m) = 0.0 ; CS%tracer_start_year(m) = 0.0 call get_param(param_file, mdl, "IDEAL_AGE_DATED_START_YEAR", CS%tracer_start_year(m), & "The date at which the dated ideal age tracer starts.", & units="years", default=0.0) endif + CS%ML_residence_num = 0 + if (do_ML_residence) then + CS%ntr = CS%ntr + 1 ; m = CS%ntr; CS%ML_residence_num = CS%ntr + CS%tr_desc(m) = var_desc("ML_age", "yr", "ML Residence Time Tracer", caller=mdl) + CS%tracer_ages(m) = .true. ; CS%growth_rate(m) = 0.0 + CS%IC_val(m) = 0.0 ; CS%young_val(m) = 0.0 ; CS%tracer_start_year(m) = 0.0 + endif + allocate(CS%tr(isd:ied,jsd:jed,nz,CS%ntr), source=0.0) do m=1,CS%ntr @@ -220,6 +239,7 @@ subroutine initialize_ideal_age_tracer(restart, day, G, GV, US, h, diag, OBC, CS logical :: OK integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz, m integer :: IsdB, IedB, JsdB, JedB + logical :: use_real_BL_depth if (.not.associated(CS)) return if (CS%ntr < 1) return @@ -277,7 +297,7 @@ end subroutine initialize_ideal_age_tracer !> Applies diapycnal diffusion, aging and regeneration at the surface to the ideal age tracers subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, US, CS, & - evap_CFL_limit, minimum_forcing_depth) + evap_CFL_limit, minimum_forcing_depth, Hml) 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)), & @@ -302,6 +322,8 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, !! be fluxed out of the top layer in a timestep [nondim] real, optional, intent(in) :: minimum_forcing_depth !< The smallest depth over which !! fluxes can be applied [H ~> m or kg m-2] + real, dimension(SZI_(G),SZJ_(G)), optional, intent(in) :: Hml !< Mixed layer depth [Z ~> m] + ! This subroutine applies diapycnal diffusion and any other column ! tracer physics or chemistry to the tracers from this file. ! This is a simple example of a set of advected passive tracers. @@ -309,13 +331,24 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, ! The arguments to this subroutine are redundant in that ! h_new(k) = h_old(k) + ea(k) - eb(k-1) + eb(k) - ea(k+1) ! Local variables + real, dimension(SZI_(G),SZJ_(G)) :: ML_layers ! Stores number of layers in mixed layer real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: h_work ! Used so that h can be modified - real :: sfc_val ! The surface value for the tracers. + real :: young_val ! The "young" value for the tracers. real :: Isecs_per_year ! The inverse of the amount of time in a year [T-1 ~> s-1] real :: year ! The time in years. - integer :: i, j, k, is, ie, js, je, nz, m + real :: layer_frac + integer :: i, j, k, is, ie, js, je, nz, m, nk + character(len=255) :: msg is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke + if (CS%use_real_BL_depth .and. .not. present(Hml)) then + call MOM_error(FATAL,"Attempting to use real boundary layer depth for ideal age tracers, but no valid boundary layer scheme was found") + endif + + if (CS%use_real_BL_depth .and. present(Hml)) then + call count_ML_layers(G, GV, h_old, Hml, ML_layers) + endif + if (.not.associated(CS)) return if (CS%ntr < 1) return @@ -340,27 +373,123 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, year = US%s_to_T*time_type_to_real(CS%Time) * Isecs_per_year do m=1,CS%ntr - if (CS%sfc_growth_rate(m) == 0.0) then - sfc_val = CS%young_val(m) + + if (CS%growth_rate(m) == 0.0) then + young_val = CS%young_val(m) else - sfc_val = CS%young_val(m) * & - exp((year-CS%tracer_start_year(m)) * CS%sfc_growth_rate(m)) + young_val = CS%young_val(m) * & + exp((year-CS%tracer_start_year(m)) * CS%growth_rate(m)) endif - do k=1,CS%nkml ; do j=js,je ; do i=is,ie - if (G%mask2dT(i,j) > 0.0) then - CS%tr(i,j,k,m) = sfc_val - else - CS%tr(i,j,k,m) = CS%land_val(m) - endif - enddo ; enddo ; enddo - enddo - do m=1,CS%ntr ; if (CS%tracer_ages(m) .and. & - (year>=CS%tracer_start_year(m))) then -!$OMP parallel do default(none) shared(is,ie,js,je,CS,nz,G,dt,Isecs_per_year,m) - do k=CS%nkml+1,nz ; do j=js,je ; do i=is,ie - CS%tr(i,j,k,m) = CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year - enddo ; enddo ; enddo - endif ; enddo + + if (m == CS%ML_residence_num) then + + if (CS%use_real_BL_depth) then + do j=js,je ; do i=is,ie + nk = floor(ML_layers(i,j)) + + do k=1,nk + if (G%mask2dT(i,j) > 0.0) then + CS%tr(i,j,k,m) = CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year + else + CS%tr(i,j,k,m) = CS%land_val(m) + endif + enddo + + k = MIN(nk+1,nz) + + write(msg,*) TRIM("ML_layers= "),ML_layers(i,j), TRIM(", k= "),(k) + call MOM_error(NOTE,msg) + + if (G%mask2dT(i,j) > 0.0) then + layer_frac = ML_layers(i,j)-nk + layer_frac = 0.9 + CS%tr(i,j,k,m) = layer_frac * (CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year) + (1.-layer_frac) * young_val + else + CS%tr(i,j,k,m) = CS%land_val(m) + endif + + + do k=nk+2,nz + if (G%mask2dT(i,j) > 0.0) then + CS%tr(i,j,k,m) = young_val + else + CS%tr(i,j,k,m) = CS%land_val(m) + endif + enddo + enddo ; enddo + + else ! use real BL depth + do j=js,je ; do i=is,ie + do k=1,CS%nkml + if (G%mask2dT(i,j) > 0.0) then + CS%tr(i,j,k,m) = CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year + else + CS%tr(i,j,k,m) = CS%land_val(m) + endif + enddo + + do k=CS%nkml+1,nz + if (G%mask2dT(i,j) > 0.0) then + CS%tr(i,j,k,m) = young_val + else + CS%tr(i,j,k,m) = CS%land_val(m) + endif + enddo + enddo ; enddo + + endif ! use real BL depth + + else ! if ML residence tracer + + if (CS%use_real_BL_depth) then + do j=js,je ; do i=is,ie + nk = floor(ML_layers(i,j)) + do k=1,nk + if (G%mask2dT(i,j) > 0.0) then + CS%tr(i,j,k,m) = young_val + else + CS%tr(i,j,k,m) = CS%land_val(m) + endif + enddo + + k = MIN(nk+1,nz) + if (G%mask2dT(i,j) > 0.0) then + layer_frac = ML_layers(i,j)-nk + CS%tr(i,j,k,m) = (1.-layer_frac) * (CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year) + layer_frac * young_val + else + CS%tr(i,j,k,m) = CS%land_val(m) + endif + + do k=nk+2,nz + if (G%mask2dT(i,j) > 0.0) then + CS%tr(i,j,k,m) = CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year + else + CS%tr(i,j,k,m) = CS%land_val(m) + endif + enddo + enddo ; enddo + + else ! use real BL depth + do k=1,CS%nkml ; do j=js,je ; do i=is,ie + if (G%mask2dT(i,j) > 0.0) then + CS%tr(i,j,k,m) = young_val + else + CS%tr(i,j,k,m) = CS%land_val(m) + endif + enddo ; enddo ; enddo + + if (CS%tracer_ages(m) .and. (year>=CS%tracer_start_year(m))) then + !$OMP parallel do default(none) shared(is,ie,js,je,CS,nz,G,dt,Isecs_per_year,m) + do k=CS%nkml+1,nz ; do j=js,je ; do i=is,ie + CS%tr(i,j,k,m) = CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year + enddo ; enddo ; enddo + endif + + + endif ! if use real BL depth + endif ! if ML residence tracer + + enddo ! loop over all tracers end subroutine ideal_age_tracer_column_physics @@ -448,6 +577,42 @@ subroutine ideal_age_example_end(CS) endif end subroutine ideal_age_example_end +subroutine count_ML_layers(G, GV, h, Hml, ML_layers) + 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)), intent(in) :: Hml !< Mixed layer depth [Z ~> m] + real, dimension(SZI_(G),SZJ_(G)), intent(out) :: ML_layers !< Number of model layers in the mixed layer + + real :: current_depth + integer :: i, j, k, is, ie, js, je, nz, m, nk + character(len=255) :: msg + is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke + + ML_layers(:,:) = 0. + do j=js,je ; do i=is,ie + +! write(msg,*) TRIM("Hml= "),Hml(i,j) +! call MOM_error(NOTE,msg) + current_depth = 0. + do k=1,nz + current_depth = current_depth + h(i,j,k)*GV%H_to_Z + if (Hml(i,j) <= current_depth) then + ML_layers(i,j) = ML_layers(i,j) + (1.0 - (current_depth - Hml(i,j)) / (h(i,j,k)*GV%H_to_Z)) +! write(msg,*) TRIM("ML_layers(i,j) found = "),ML_layers(i,j) +! call MOM_error(NOTE,msg) + exit + else + ML_layers(i,j) = ML_layers(i,j) + 1.0 +! write(msg,*) TRIM("ML_layers(i,j) adding = "),ML_layers(i,j) +! call MOM_error(NOTE,msg) + endif + enddo + enddo ; enddo + +end subroutine count_ML_layers + !> \namespace ideal_age_example !! !! Originally by Robert Hallberg, 2002 From f415a7f5cc844730fd483bd5f4ad36ab04ec2fce Mon Sep 17 00:00:00 2001 From: Scott Bachman Date: Fri, 29 Jul 2022 12:22:54 -0600 Subject: [PATCH 04/27] Shortens a line and removes whitespace --- src/tracer/ideal_age_example.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tracer/ideal_age_example.F90 b/src/tracer/ideal_age_example.F90 index 92aab231a2..460b5cba41 100644 --- a/src/tracer/ideal_age_example.F90 +++ b/src/tracer/ideal_age_example.F90 @@ -342,7 +342,8 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke if (CS%use_real_BL_depth .and. .not. present(Hml)) then - call MOM_error(FATAL,"Attempting to use real boundary layer depth for ideal age tracers, but no valid boundary layer scheme was found") + call MOM_error(FATAL,"Attempting to use real boundary layer depth for ideal age tracers, & + but no valid boundary layer scheme was found") endif if (CS%use_real_BL_depth .and. present(Hml)) then @@ -599,7 +600,7 @@ subroutine count_ML_layers(G, GV, h, Hml, ML_layers) do k=1,nz current_depth = current_depth + h(i,j,k)*GV%H_to_Z if (Hml(i,j) <= current_depth) then - ML_layers(i,j) = ML_layers(i,j) + (1.0 - (current_depth - Hml(i,j)) / (h(i,j,k)*GV%H_to_Z)) + ML_layers(i,j) = ML_layers(i,j) + (1.0 - (current_depth - Hml(i,j)) / (h(i,j,k)*GV%H_to_Z)) ! write(msg,*) TRIM("ML_layers(i,j) found = "),ML_layers(i,j) ! call MOM_error(NOTE,msg) exit From 2428684ac7537412794297e5329c98de2b648c6f Mon Sep 17 00:00:00 2001 From: Scott Bachman Date: Fri, 29 Jul 2022 12:37:09 -0600 Subject: [PATCH 05/27] !! ----> !< --- src/tracer/ideal_age_example.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracer/ideal_age_example.F90 b/src/tracer/ideal_age_example.F90 index 460b5cba41..c1d12b1594 100644 --- a/src/tracer/ideal_age_example.F90 +++ b/src/tracer/ideal_age_example.F90 @@ -55,7 +55,7 @@ module ideal_age_example !! surface value equals young_val, in years. logical :: use_real_BL_depth !< If true, uses the BL scheme to determine the number of !! layers above the BL depth instead of the fixed nkml value. - integer :: ML_residence_num !! The tracer number assigned to the ML residence tracer in this module + integer :: ML_residence_num !< The tracer number assigned to the ML residence tracer in this module logical :: tracers_may_reinit !< If true, these tracers be set up via the initialization code if !! they are not found in the restart files. logical :: tracer_ages(NTR_MAX) !< Indicates whether each tracer ages. From 0d86acd523280a7f762ac9aaa48b0b1d761499ec Mon Sep 17 00:00:00 2001 From: Scott Bachman Date: Fri, 29 Jul 2022 12:46:01 -0600 Subject: [PATCH 06/27] Shortened line length to make dOxygen happy --- src/tracer/ideal_age_example.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tracer/ideal_age_example.F90 b/src/tracer/ideal_age_example.F90 index c1d12b1594..cc0f8c4cdf 100644 --- a/src/tracer/ideal_age_example.F90 +++ b/src/tracer/ideal_age_example.F90 @@ -404,7 +404,8 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, if (G%mask2dT(i,j) > 0.0) then layer_frac = ML_layers(i,j)-nk layer_frac = 0.9 - CS%tr(i,j,k,m) = layer_frac * (CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year) + (1.-layer_frac) * young_val + CS%tr(i,j,k,m) = layer_frac * (CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt & + *Isecs_per_year) + (1.-layer_frac) * young_val else CS%tr(i,j,k,m) = CS%land_val(m) endif @@ -456,7 +457,8 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, k = MIN(nk+1,nz) if (G%mask2dT(i,j) > 0.0) then layer_frac = ML_layers(i,j)-nk - CS%tr(i,j,k,m) = (1.-layer_frac) * (CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year) + layer_frac * young_val + CS%tr(i,j,k,m) = (1.-layer_frac) * (CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt & + *Isecs_per_year) + layer_frac * young_val else CS%tr(i,j,k,m) = CS%land_val(m) endif From 5ac624241c40e4381efe724ade3e0dab5e442368 Mon Sep 17 00:00:00 2001 From: Scott Bachman Date: Fri, 29 Jul 2022 15:41:49 -0600 Subject: [PATCH 07/27] All references to "mixed layer" in the ideal age module now refer to "boundary layer" instead. --- src/tracer/ideal_age_example.F90 | 91 ++++++++++++++------------------ 1 file changed, 41 insertions(+), 50 deletions(-) diff --git a/src/tracer/ideal_age_example.F90 b/src/tracer/ideal_age_example.F90 index cc0f8c4cdf..7351a7e459 100644 --- a/src/tracer/ideal_age_example.F90 +++ b/src/tracer/ideal_age_example.F90 @@ -31,7 +31,7 @@ module ideal_age_example public register_ideal_age_tracer, initialize_ideal_age_tracer public ideal_age_tracer_column_physics, ideal_age_tracer_surface_state public ideal_age_stock, ideal_age_example_end -public count_ML_layers +public count_BL_layers integer, parameter :: NTR_MAX = 4 !< the maximum number of tracers in this module. @@ -39,8 +39,8 @@ module ideal_age_example type, public :: ideal_age_tracer_CS ; private integer :: ntr !< The number of tracers that are actually used. logical :: coupled_tracers = .false. !< These tracers are not offered to the coupler. - integer :: nkml !< The number of layers in the mixed layer. The ideal - !1 age tracers are reset in the top nkml layers. + integer :: nkbl !< The number of layers in the boundary layer. The ideal + !1 age tracers are reset in the top nkbl layers. character(len=200) :: IC_file !< The file in which the age-tracer initial values !! can be found, or an empty string for internal initialization. logical :: Z_IC_file !< If true, the IC_file is in Z-space. The default is false. @@ -54,8 +54,8 @@ module ideal_age_example real, dimension(NTR_MAX) :: tracer_start_year !< The year in which tracers start aging, or at which the !! surface value equals young_val, in years. logical :: use_real_BL_depth !< If true, uses the BL scheme to determine the number of - !! layers above the BL depth instead of the fixed nkml value. - integer :: ML_residence_num !< The tracer number assigned to the ML residence tracer in this module + !! layers above the BL depth instead of the fixed nkbl value. + integer :: BL_residence_num !< The tracer number assigned to the BL residence tracer in this module logical :: tracers_may_reinit !< If true, these tracers be set up via the initialization code if !! they are not found in the restart files. logical :: tracer_ages(NTR_MAX) !< Indicates whether each tracer ages. @@ -92,7 +92,7 @@ function register_ideal_age_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS) character(len=48) :: var_name ! The variable's name. real, pointer :: tr_ptr(:,:,:) => NULL() logical :: register_ideal_age_tracer - logical :: do_ideal_age, do_vintage, do_ideal_age_dated, do_ML_residence + logical :: do_ideal_age, do_vintage, do_ideal_age_dated, do_BL_residence integer :: isd, ied, jsd, jed, nz, m isd = HI%isd ; ied = HI%ied ; jsd = HI%jsd ; jed = HI%jed ; nz = GV%ke @@ -107,21 +107,21 @@ function register_ideal_age_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS) call log_version(param_file, mdl, version, "") call get_param(param_file, mdl, "DO_IDEAL_AGE", do_ideal_age, & "If true, use an ideal age tracer that is set to 0 age "//& - "in the mixed layer and ages at unit rate in the interior.", & + "in the boundary layer and ages at unit rate in the interior.", & default=.true.) call get_param(param_file, mdl, "DO_IDEAL_VINTAGE", do_vintage, & "If true, use an ideal vintage tracer that is set to an "//& - "exponentially increasing value in the mixed layer and "//& + "exponentially increasing value in the boundary layer and "//& "is conserved thereafter.", default=.false.) call get_param(param_file, mdl, "DO_IDEAL_AGE_DATED", do_ideal_age_dated, & "If true, use an ideal age tracer that is everywhere 0 "//& "before IDEAL_AGE_DATED_START_YEAR, but the behaves like "//& "the standard ideal age tracer - i.e. is set to 0 age in "//& - "the mixed layer and ages at unit rate in the interior.", & + "the boundary layer and ages at unit rate in the interior.", & default=.false.) - call get_param(param_file, mdl, "DO_ML_RESIDENCE", do_ML_residence, & + call get_param(param_file, mdl, "DO_BL_RESIDENCE", do_BL_residence, & "If true, use a residence tracer that is set to 0 age "//& - "in the interior and ages at unit rate in the mixed layer.", & + "in the interior and ages at unit rate in the boundary layer.", & default=.false.) call get_param(param_file, mdl, "USE_REAL_BL_DEPTH", CS%use_real_BL_depth, & "If true, the ideal age tracers will use the boundary layer "//& @@ -176,10 +176,10 @@ function register_ideal_age_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS) units="years", default=0.0) endif - CS%ML_residence_num = 0 - if (do_ML_residence) then - CS%ntr = CS%ntr + 1 ; m = CS%ntr; CS%ML_residence_num = CS%ntr - CS%tr_desc(m) = var_desc("ML_age", "yr", "ML Residence Time Tracer", caller=mdl) + CS%BL_residence_num = 0 + if (do_BL_residence) then + CS%ntr = CS%ntr + 1 ; m = CS%ntr; CS%BL_residence_num = CS%ntr + CS%tr_desc(m) = var_desc("BL_age", "yr", "BL Residence Time Tracer", caller=mdl) CS%tracer_ages(m) = .true. ; CS%growth_rate(m) = 0.0 CS%IC_val(m) = 0.0 ; CS%young_val(m) = 0.0 ; CS%tracer_start_year(m) = 0.0 endif @@ -249,7 +249,7 @@ subroutine initialize_ideal_age_tracer(restart, day, G, GV, US, h, diag, OBC, CS CS%Time => day CS%diag => diag - CS%nkml = max(GV%nkml,1) + CS%nkbl = max(GV%nkbl,1) do m=1,CS%ntr call query_vardesc(CS%tr_desc(m), name=name, & @@ -297,7 +297,7 @@ end subroutine initialize_ideal_age_tracer !> Applies diapycnal diffusion, aging and regeneration at the surface to the ideal age tracers subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, US, CS, & - evap_CFL_limit, minimum_forcing_depth, Hml) + evap_CFL_limit, minimum_forcing_depth, Hbl) 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)), & @@ -322,7 +322,7 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, !! be fluxed out of the top layer in a timestep [nondim] real, optional, intent(in) :: minimum_forcing_depth !< The smallest depth over which !! fluxes can be applied [H ~> m or kg m-2] - real, dimension(SZI_(G),SZJ_(G)), optional, intent(in) :: Hml !< Mixed layer depth [Z ~> m] + real, dimension(SZI_(G),SZJ_(G)), optional, intent(in) :: Hbl !< Boundary layer depth [Z ~> m] ! This subroutine applies diapycnal diffusion and any other column ! tracer physics or chemistry to the tracers from this file. @@ -331,7 +331,7 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, ! The arguments to this subroutine are redundant in that ! h_new(k) = h_old(k) + ea(k) - eb(k-1) + eb(k) - ea(k+1) ! Local variables - real, dimension(SZI_(G),SZJ_(G)) :: ML_layers ! Stores number of layers in mixed layer + real, dimension(SZI_(G),SZJ_(G)) :: BL_layers ! Stores number of layers in boundary layer real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: h_work ! Used so that h can be modified real :: young_val ! The "young" value for the tracers. real :: Isecs_per_year ! The inverse of the amount of time in a year [T-1 ~> s-1] @@ -341,13 +341,13 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, character(len=255) :: msg is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke - if (CS%use_real_BL_depth .and. .not. present(Hml)) then + if (CS%use_real_BL_depth .and. .not. present(Hbl)) then call MOM_error(FATAL,"Attempting to use real boundary layer depth for ideal age tracers, & but no valid boundary layer scheme was found") endif - if (CS%use_real_BL_depth .and. present(Hml)) then - call count_ML_layers(G, GV, h_old, Hml, ML_layers) + if (CS%use_real_BL_depth .and. present(Hbl)) then + call count_BL_layers(G, GV, h_old, Hbl, BL_layers) endif if (.not.associated(CS)) return @@ -382,11 +382,11 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, exp((year-CS%tracer_start_year(m)) * CS%growth_rate(m)) endif - if (m == CS%ML_residence_num) then + if (m == CS%BL_residence_num) then if (CS%use_real_BL_depth) then do j=js,je ; do i=is,ie - nk = floor(ML_layers(i,j)) + nk = floor(BL_layers(i,j)) do k=1,nk if (G%mask2dT(i,j) > 0.0) then @@ -398,11 +398,8 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, k = MIN(nk+1,nz) - write(msg,*) TRIM("ML_layers= "),ML_layers(i,j), TRIM(", k= "),(k) - call MOM_error(NOTE,msg) - if (G%mask2dT(i,j) > 0.0) then - layer_frac = ML_layers(i,j)-nk + layer_frac = BL_layers(i,j)-nk layer_frac = 0.9 CS%tr(i,j,k,m) = layer_frac * (CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt & *Isecs_per_year) + (1.-layer_frac) * young_val @@ -422,7 +419,7 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, else ! use real BL depth do j=js,je ; do i=is,ie - do k=1,CS%nkml + do k=1,CS%nkbl if (G%mask2dT(i,j) > 0.0) then CS%tr(i,j,k,m) = CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year else @@ -430,7 +427,7 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, endif enddo - do k=CS%nkml+1,nz + do k=CS%nkbl+1,nz if (G%mask2dT(i,j) > 0.0) then CS%tr(i,j,k,m) = young_val else @@ -441,11 +438,11 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, endif ! use real BL depth - else ! if ML residence tracer + else ! if BL residence tracer if (CS%use_real_BL_depth) then do j=js,je ; do i=is,ie - nk = floor(ML_layers(i,j)) + nk = floor(BL_layers(i,j)) do k=1,nk if (G%mask2dT(i,j) > 0.0) then CS%tr(i,j,k,m) = young_val @@ -456,7 +453,7 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, k = MIN(nk+1,nz) if (G%mask2dT(i,j) > 0.0) then - layer_frac = ML_layers(i,j)-nk + layer_frac = BL_layers(i,j)-nk CS%tr(i,j,k,m) = (1.-layer_frac) * (CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt & *Isecs_per_year) + layer_frac * young_val else @@ -473,7 +470,7 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, enddo ; enddo else ! use real BL depth - do k=1,CS%nkml ; do j=js,je ; do i=is,ie + do k=1,CS%nkbl ; do j=js,je ; do i=is,ie if (G%mask2dT(i,j) > 0.0) then CS%tr(i,j,k,m) = young_val else @@ -483,14 +480,14 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, if (CS%tracer_ages(m) .and. (year>=CS%tracer_start_year(m))) then !$OMP parallel do default(none) shared(is,ie,js,je,CS,nz,G,dt,Isecs_per_year,m) - do k=CS%nkml+1,nz ; do j=js,je ; do i=is,ie + do k=CS%nkbl+1,nz ; do j=js,je ; do i=is,ie CS%tr(i,j,k,m) = CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year enddo ; enddo ; enddo endif endif ! if use real BL depth - endif ! if ML residence tracer + endif ! if BL residence tracer enddo ! loop over all tracers @@ -580,41 +577,35 @@ subroutine ideal_age_example_end(CS) endif end subroutine ideal_age_example_end -subroutine count_ML_layers(G, GV, h, Hml, ML_layers) +subroutine count_BL_layers(G, GV, h, Hbl, BL_layers) 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)), intent(in) :: Hml !< Mixed layer depth [Z ~> m] - real, dimension(SZI_(G),SZJ_(G)), intent(out) :: ML_layers !< Number of model layers in the mixed layer + real, dimension(SZI_(G),SZJ_(G)), intent(in) :: Hbl !< Boundary layer depth [Z ~> m] + real, dimension(SZI_(G),SZJ_(G)), intent(out) :: BL_layers !< Number of model layers in the boundary layer real :: current_depth integer :: i, j, k, is, ie, js, je, nz, m, nk character(len=255) :: msg is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke - ML_layers(:,:) = 0. + BL_layers(:,:) = 0. do j=js,je ; do i=is,ie -! write(msg,*) TRIM("Hml= "),Hml(i,j) -! call MOM_error(NOTE,msg) current_depth = 0. do k=1,nz current_depth = current_depth + h(i,j,k)*GV%H_to_Z - if (Hml(i,j) <= current_depth) then - ML_layers(i,j) = ML_layers(i,j) + (1.0 - (current_depth - Hml(i,j)) / (h(i,j,k)*GV%H_to_Z)) -! write(msg,*) TRIM("ML_layers(i,j) found = "),ML_layers(i,j) -! call MOM_error(NOTE,msg) + if (Hbl(i,j) <= current_depth) then + BL_layers(i,j) = BL_layers(i,j) + (1.0 - (current_depth - Hbl(i,j)) / (h(i,j,k)*GV%H_to_Z)) exit else - ML_layers(i,j) = ML_layers(i,j) + 1.0 -! write(msg,*) TRIM("ML_layers(i,j) adding = "),ML_layers(i,j) -! call MOM_error(NOTE,msg) + BL_layers(i,j) = BL_layers(i,j) + 1.0 endif enddo enddo ; enddo -end subroutine count_ML_layers +end subroutine count_BL_layers !> \namespace ideal_age_example !! From e300296ac5c9fd9c3e6cf1aec791c70679dd75ba Mon Sep 17 00:00:00 2001 From: Scott Bachman Date: Mon, 1 Aug 2022 11:09:12 -0600 Subject: [PATCH 08/27] Changed GV%nkbl back to GV%nkml --- src/tracer/ideal_age_example.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracer/ideal_age_example.F90 b/src/tracer/ideal_age_example.F90 index 7351a7e459..ea9cbb3063 100644 --- a/src/tracer/ideal_age_example.F90 +++ b/src/tracer/ideal_age_example.F90 @@ -249,7 +249,7 @@ subroutine initialize_ideal_age_tracer(restart, day, G, GV, US, h, diag, OBC, CS CS%Time => day CS%diag => diag - CS%nkbl = max(GV%nkbl,1) + CS%nkbl = max(GV%nkml,1) do m=1,CS%ntr call query_vardesc(CS%tr_desc(m), name=name, & From dfb37154abff846b5edf5116ef0940d77df6f61d Mon Sep 17 00:00:00 2001 From: Scott Bachman Date: Mon, 1 Aug 2022 11:16:47 -0600 Subject: [PATCH 09/27] Changed parameter reference for ideal_age_physics to Hbl=Hml --- src/tracer/MOM_tracer_flow_control.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tracer/MOM_tracer_flow_control.F90 b/src/tracer/MOM_tracer_flow_control.F90 index 3dac584571..7520db820d 100644 --- a/src/tracer/MOM_tracer_flow_control.F90 +++ b/src/tracer/MOM_tracer_flow_control.F90 @@ -469,7 +469,7 @@ subroutine call_tracer_column_fns(h_old, h_new, ea, eb, fluxes, Hml, dt, G, GV, G, GV, US, CS%ideal_age_tracer_CSp, & evap_CFL_limit=evap_CFL_limit, & minimum_forcing_depth=minimum_forcing_depth, & - Hml=Hml) + Hbl=Hml) if (CS%use_regional_dyes) & call dye_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & G, GV, US, CS%dye_tracer_CSp, & @@ -545,7 +545,7 @@ subroutine call_tracer_column_fns(h_old, h_new, ea, eb, fluxes, Hml, dt, G, GV, G, GV, US, CS%RGC_tracer_CSp) if (CS%use_ideal_age) & call ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & - G, GV, US, CS%ideal_age_tracer_CSp, Hml=Hml) + G, GV, US, CS%ideal_age_tracer_CSp, Hbl=Hml) if (CS%use_regional_dyes) & call dye_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & G, GV, US, CS%dye_tracer_CSp) From cfd7c0bdec86c07231447c3ed1a4ac9f93b6b47a Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Thu, 22 Sep 2022 08:17:18 -0600 Subject: [PATCH 10/27] Rename parameter SMOOTH_RI to N_SMOOTH_RI In preparation for implementing the option to apply a vertical smooth filter in the Richardson number multiple times, the parameter SMOOTH_RI (logical) was renamed to N_SMOOTH_RI (interger). If N_SMOOTH_RI = 0 (default), smoothing is not performed. If N_SMOOTH_RI > 0, smoothing will be applied N_SMOOTH_RI times. --- src/parameterizations/vertical/MOM_CVMix_shear.F90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/parameterizations/vertical/MOM_CVMix_shear.F90 b/src/parameterizations/vertical/MOM_CVMix_shear.F90 index 7ec45dbe11..a84ec9ddd1 100644 --- a/src/parameterizations/vertical/MOM_CVMix_shear.F90 +++ b/src/parameterizations/vertical/MOM_CVMix_shear.F90 @@ -31,7 +31,7 @@ module MOM_CVMix_shear type, public :: CVMix_shear_cs ! TODO: private logical :: use_LMD94 !< Flags to use the LMD94 scheme logical :: use_PP81 !< Flags to use Pacanowski and Philander (JPO 1981) - logical :: smooth_ri !< If true, smooth Ri using a 1-2-1 filter + integer :: n_smooth_ri !< Number of times to smooth Ri using a 1-2-1 filter real :: Ri_zero !< LMD94 critical Richardson number real :: Nu_zero !< LMD94 maximum interior diffusivity real :: KPP_exp !< Exponent of unitless factor of diff. @@ -147,7 +147,7 @@ subroutine calculate_CVMix_shear(u_H, v_H, h, tv, kd, kv, G, GV, US, CS ) if (CS%id_ri_grad > 0) CS%ri_grad(i,j,:) = Ri_Grad(:) - if (CS%smooth_ri) then + if (CS%n_smooth_ri) then ! 1) fill Ri_grad in vanished layers with adjacent value do k = 2, GV%ke if (h(i,j,k) <= epsln) Ri_grad(k) = Ri_grad(k-1) @@ -274,10 +274,10 @@ logical function CVMix_shear_init(Time, G, GV, US, param_file, diag, CS) "Exponent of unitless factor of diffusivities, "// & "for KPP internal shear mixing scheme." & ,units="nondim", default=3.0) - call get_param(param_file, mdl, "SMOOTH_RI", CS%smooth_ri, & - "If true, vertically smooth the Richardson "// & - "number by applying a 1-2-1 filter once.", & - default = .false.) + call get_param(param_file, mdl, "N_SMOOTH_RI", CS%n_smooth_ri, & + "If > 0, vertically smooth the Richardson "// & + "number by applying a 1-2-1 filter N_SMOOTH_RI times.", & + default = 0) call cvmix_init_shear(mix_scheme=CS%Mix_Scheme, & KPP_nu_zero=CS%Nu_Zero, & KPP_Ri_zero=CS%Ri_zero, & From 09278521c10ba261b52e68e834b9899628455be3 Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Thu, 22 Sep 2022 08:39:27 -0600 Subject: [PATCH 11/27] Modify gradient Richarson number diagnostics Currently, there are two diagnostics related to the gradient Richarson number and these are described as follows: * ri_grad_shear : Gradient Richarson number used by MOM_CVMix_shear module; * ri_grad_shear_smooth : Smoothed gradient Richarson number used by MOM_CVMix_shear module. The description for ri_grad_shear is misleading. If smoothing is applied, ri_grad_shear *is not* the RI number used by MOM_CVMix_shear module. In this commit. I propose to avoid this potential confusion by renaming ri_grad_shear_smooth to ri_grad_shear_orig and, if N_SMOOTH_RI > 0, use ri_grad_shear to store the smoothed profiles. * ri_grad_shear_orig : Original gradient Richarson number, before smoothing was applied. This is part of the MOM_CVMix_shear module and only available when N_SMOOTH_RI > 0. No change in answers for GMOM. --- .../vertical/MOM_CVMix_shear.F90 | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/parameterizations/vertical/MOM_CVMix_shear.F90 b/src/parameterizations/vertical/MOM_CVMix_shear.F90 index a84ec9ddd1..fca11423cb 100644 --- a/src/parameterizations/vertical/MOM_CVMix_shear.F90 +++ b/src/parameterizations/vertical/MOM_CVMix_shear.F90 @@ -39,14 +39,14 @@ module MOM_CVMix_shear real, allocatable, dimension(:,:,:) :: N2 !< Squared Brunt-Vaisala frequency [T-2 ~> s-2] real, allocatable, dimension(:,:,:) :: S2 !< Squared shear frequency [T-2 ~> s-2] real, allocatable, dimension(:,:,:) :: ri_grad !< Gradient Richardson number - real, allocatable, dimension(:,:,:) :: ri_grad_smooth !< Gradient Richardson number - !! after smoothing + real, allocatable, dimension(:,:,:) :: ri_grad_orig !< Gradient Richardson number + !! before smoothing character(10) :: Mix_Scheme !< Mixing scheme name (string) type(diag_ctrl), pointer :: diag => NULL() !< Pointer to the diagnostics control structure !>@{ Diagnostic handles integer :: id_N2 = -1, id_S2 = -1, id_ri_grad = -1, id_kv = -1, id_kd = -1 - integer :: id_ri_grad_smooth = -1 + integer :: id_ri_grad_orig = -1 !>@} end type CVMix_shear_cs @@ -145,9 +145,9 @@ subroutine calculate_CVMix_shear(u_H, v_H, h, tv, kd, kv, G, GV, US, CS ) Ri_grad(GV%ke+1) = Ri_grad(GV%ke) - if (CS%id_ri_grad > 0) CS%ri_grad(i,j,:) = Ri_Grad(:) + if (CS%id_ri_grad_orig > 0) CS%ri_grad_orig(i,j,:) = Ri_Grad(:) - if (CS%n_smooth_ri) then + if (CS%n_smooth_ri > 0) then ! 1) fill Ri_grad in vanished layers with adjacent value do k = 2, GV%ke if (h(i,j,k) <= epsln) Ri_grad(k) = Ri_grad(k-1) @@ -163,7 +163,7 @@ subroutine calculate_CVMix_shear(u_H, v_H, h, tv, kd, kv, G, GV, US, CS ) dummy = 0.25 * Ri_grad(k) enddo - if (CS%id_ri_grad_smooth > 0) CS%ri_grad_smooth(i,j,:) = Ri_Grad(:) + if (CS%id_ri_grad > 0) CS%ri_grad(i,j,:) = Ri_Grad(:) endif do K=1,GV%ke+1 @@ -190,7 +190,7 @@ subroutine calculate_CVMix_shear(u_H, v_H, h, tv, kd, kv, G, GV, US, CS ) if (CS%id_N2 > 0) call post_data(CS%id_N2, CS%N2, CS%diag) if (CS%id_S2 > 0) call post_data(CS%id_S2, CS%S2, CS%diag) if (CS%id_ri_grad > 0) call post_data(CS%id_ri_grad, CS%ri_grad, CS%diag) - if (CS%id_ri_grad_smooth > 0) call post_data(CS%id_ri_grad_smooth ,CS%ri_grad_smooth, CS%diag) + if (CS%id_ri_grad_orig > 0) call post_data(CS%id_ri_grad_orig ,CS%ri_grad_orig, CS%diag) end subroutine calculate_CVMix_shear @@ -304,11 +304,12 @@ logical function CVMix_shear_init(Time, G, GV, US, param_file, diag, CS) allocate( CS%ri_grad( SZI_(G), SZJ_(G), SZK_(GV)+1 ), source=1.e8 ) endif - CS%id_ri_grad_smooth = register_diag_field('ocean_model', 'ri_grad_shear_smooth', & + CS%id_ri_grad_orig = register_diag_field('ocean_model', 'ri_grad_shear_orig', & diag%axesTi, Time, & - 'Smoothed gradient Richarson number used by MOM_CVMix_shear module','nondim') - if (CS%id_ri_grad_smooth > 0) then !Initialize w/ large Richardson value - allocate( CS%ri_grad_smooth( SZI_(G), SZJ_(G), SZK_(GV)+1 ), source=1.e8 ) + 'Original gradient Richarson number, before smoothing was applied. This is '//& + 'part of the MOM_CVMix_shear module and only available when N_SMOOTH_RI > 0','nondim') + if (CS%id_ri_grad_orig > 0 .or. CS%n_smooth_ri > 0) then !Initialize w/ large Richardson value + allocate( CS%ri_grad_orig( SZI_(G), SZJ_(G), SZK_(GV)+1 ), source=1.e8 ) endif CS%id_kd = register_diag_field('ocean_model', 'kd_shear_CVMix', diag%axesTi, Time, & From b4440417c78eb585503cac8dc9f821bcef315e1e Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Thu, 22 Sep 2022 14:16:21 -0600 Subject: [PATCH 12/27] Adds option to smooth gradient Ri multiple times This commit adds the option to smooth the gradient Richardson number multiple times using a 1-2-1 filter. The number of times that the filter is applied is controlled by parameter N_SMOOTH_RI. --- .../vertical/MOM_CVMix_shear.F90 | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/parameterizations/vertical/MOM_CVMix_shear.F90 b/src/parameterizations/vertical/MOM_CVMix_shear.F90 index fca11423cb..e3906e9df2 100644 --- a/src/parameterizations/vertical/MOM_CVMix_shear.F90 +++ b/src/parameterizations/vertical/MOM_CVMix_shear.F90 @@ -72,7 +72,7 @@ subroutine calculate_CVMix_shear(u_H, v_H, h, tv, kd, kv, G, GV, US, CS ) type(CVMix_shear_cs), pointer :: CS !< The control structure returned by a previous !! call to CVMix_shear_init. ! Local variables - integer :: i, j, k, kk, km1 + integer :: i, j, k, kk, km1, s real :: GoRho ! Gravitational acceleration divided by density [Z T-2 R-1 ~> m4 s-2 kg-1] real :: pref ! Interface pressures [R L2 T-2 ~> Pa] real :: DU, DV ! Velocity differences [L T-1 ~> m s-1] @@ -85,7 +85,8 @@ subroutine calculate_CVMix_shear(u_H, v_H, h, tv, kd, kv, G, GV, US, CS ) 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) :: Ri_Grad !< Gradient Richardson number [nondim] + real, dimension(GV%ke+1) :: Ri_Grad_prev !< Gradient Richardson number before s.th smoothing iteration [nondim] real, dimension(GV%ke+1) :: Kvisc !< Vertical viscosity at interfaces [m2 s-1] real, dimension(GV%ke+1) :: Kdiff !< Diapycnal diffusivity at interfaces [m2 s-1] real :: epsln !< Threshold to identify vanished layers [H ~> m or kg m-2] @@ -145,9 +146,10 @@ subroutine calculate_CVMix_shear(u_H, v_H, h, tv, kd, kv, G, GV, US, CS ) Ri_grad(GV%ke+1) = Ri_grad(GV%ke) - if (CS%id_ri_grad_orig > 0) CS%ri_grad_orig(i,j,:) = Ri_Grad(:) - if (CS%n_smooth_ri > 0) then + + if (CS%id_ri_grad_orig > 0) CS%ri_grad_orig(i,j,:) = Ri_Grad(:) + ! 1) fill Ri_grad in vanished layers with adjacent value do k = 2, GV%ke if (h(i,j,k) <= epsln) Ri_grad(k) = Ri_grad(k-1) @@ -155,17 +157,24 @@ subroutine calculate_CVMix_shear(u_H, v_H, h, tv, kd, kv, G, GV, US, CS ) Ri_grad(GV%ke+1) = Ri_grad(GV%ke) - ! 2) vertically smooth Ri with 1-2-1 filter - dummy = 0.25 * Ri_grad(2) - Ri_grad(GV%ke+1) = Ri_grad(GV%ke) - do k = 3, GV%ke - Ri_Grad(k) = dummy + 0.5 * Ri_Grad(k) + 0.25 * Ri_grad(k+1) - dummy = 0.25 * Ri_grad(k) + do s=1,CS%n_smooth_ri + + Ri_Grad_prev(:) = Ri_Grad(:) + + ! 2) vertically smooth Ri with 1-2-1 filter + dummy = 0.25 * Ri_grad_prev(2) + do k = 3, GV%ke + Ri_Grad(k) = dummy + 0.5 * Ri_Grad_prev(k) + 0.25 * Ri_grad_prev(k+1) + dummy = 0.25 * Ri_grad(k) + enddo enddo - if (CS%id_ri_grad > 0) CS%ri_grad(i,j,:) = Ri_Grad(:) + Ri_grad(GV%ke+1) = Ri_grad(GV%ke) + endif + if (CS%id_ri_grad > 0) CS%ri_grad(i,j,:) = Ri_Grad(:) + do K=1,GV%ke+1 Kvisc(K) = US%Z2_T_to_m2_s * kv(i,j,K) Kdiff(K) = US%Z2_T_to_m2_s * kd(i,j,K) @@ -304,10 +313,12 @@ logical function CVMix_shear_init(Time, G, GV, US, param_file, diag, CS) allocate( CS%ri_grad( SZI_(G), SZJ_(G), SZK_(GV)+1 ), source=1.e8 ) endif - CS%id_ri_grad_orig = register_diag_field('ocean_model', 'ri_grad_shear_orig', & - diag%axesTi, Time, & - 'Original gradient Richarson number, before smoothing was applied. This is '//& - 'part of the MOM_CVMix_shear module and only available when N_SMOOTH_RI > 0','nondim') + if (CS%n_smooth_ri > 0) then + CS%id_ri_grad_orig = register_diag_field('ocean_model', 'ri_grad_shear_orig', & + diag%axesTi, Time, & + 'Original gradient Richarson number, before smoothing was applied. This is '//& + 'part of the MOM_CVMix_shear module and only available when N_SMOOTH_RI > 0','nondim') + endif if (CS%id_ri_grad_orig > 0 .or. CS%n_smooth_ri > 0) then !Initialize w/ large Richardson value allocate( CS%ri_grad_orig( SZI_(G), SZJ_(G), SZK_(GV)+1 ), source=1.e8 ) endif From 0cf34d352e59f8a202e93de6d9b2290bb06ef74e Mon Sep 17 00:00:00 2001 From: Gustavo Marques Date: Fri, 7 Oct 2022 11:35:25 -0600 Subject: [PATCH 13/27] Fix string order in regional_section The correct order is lon_min lon_max lat_min lat_max ... and not lat_min lat_max lon_min lon_max. --- src/framework/_Diagnostics.dox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/_Diagnostics.dox b/src/framework/_Diagnostics.dox index 3db345ca1a..0be318f580 100644 --- a/src/framework/_Diagnostics.dox +++ b/src/framework/_Diagnostics.dox @@ -90,7 +90,7 @@ An arbitrary number of lines, one per diagnostic field: "average" or "mean" performs a time-average. "min" or "max" diagnose the minium or maxium over each time period. -- `regional_section` : "none" means global output. A string of six space separated numbers, "lat_min, lat_max, lon_min, lon_max, vert_min, vert_max", limits the diagnostic to a region. +- `regional_section` : "none" means global output. A string of six space separated numbers, "lon_min lon_max lat_min lat_max vert_min vert_max", limits the diagnostic to a region. - `packing` : Data representation in the file. 1 means "real*8", 2 means "real*4", 4 mean 16-bit integers, 8 means 1-byte. From 380864138fb936e3e0bd76bb5155d74200e89db8 Mon Sep 17 00:00:00 2001 From: Alistair Adcroft Date: Wed, 7 Dec 2022 13:58:54 -0500 Subject: [PATCH 14/27] Switch from mpich to openmpi Testing to see if GH actions is failing due to MPI installation --- .github/actions/ubuntu-setup/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/ubuntu-setup/action.yml b/.github/actions/ubuntu-setup/action.yml index 3fd2ea13cf..3f3ba5f0b6 100644 --- a/.github/actions/ubuntu-setup/action.yml +++ b/.github/actions/ubuntu-setup/action.yml @@ -13,7 +13,7 @@ runs: sudo apt-get install netcdf-bin sudo apt-get install libnetcdf-dev sudo apt-get install libnetcdff-dev - sudo apt-get install mpich - sudo apt-get install libmpich-dev + sudo apt-get install openmpi-bin + sudo apt-get install libopenmpi-dev sudo apt-get install linux-tools-common echo "::endgroup::" From a80b91dedf974415a73d13c1d8f653b1f6eb8350 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Mon, 12 Dec 2022 11:13:50 -0700 Subject: [PATCH 15/27] use more cesm style logging --- config_src/drivers/nuopc_cap/mom_cap.F90 | 130 ++++++++++++----------- 1 file changed, 69 insertions(+), 61 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index b01e2019da..f1f2bdced6 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -5,16 +5,14 @@ module MOM_cap_mod use constants_mod, only: constants_init use diag_manager_mod, only: diag_manager_init, diag_manager_end use field_manager_mod, only: field_manager_init, field_manager_end -use fms_mod, only: fms_init, fms_end, open_namelist_file, check_nml_error -use fms_mod, only: close_file, file_exist, uppercase -use fms_io_mod, only: fms_io_exit -use mpp_domains_mod, only: domain2d, mpp_get_compute_domain, mpp_get_compute_domains +use mom_coms_infra, only: MOM_infra_init, MOM_infra_end +use mom_io_infra, only: io_infra_end +use mom_domain_infra, only: get_domain_extent +use MOM_io, only: stdout +use mpp_domains_mod, only: mpp_get_compute_domains use mpp_domains_mod, only: mpp_get_ntile_count, mpp_get_pelist, mpp_get_global_domain use mpp_domains_mod, only: mpp_get_domain_npes -use mpp_io_mod, only: mpp_open, MPP_RDONLY, MPP_ASCII, MPP_OVERWR, MPP_APPEND, mpp_close, MPP_SINGLE -use mpp_mod, only: stdlog, stdout, mpp_root_pe, mpp_clock_id -use mpp_mod, only: mpp_clock_begin, mpp_clock_end, MPP_CLOCK_SYNC -use mpp_mod, only: MPP_CLOCK_DETAILED, CLOCK_COMPONENT, MAXPES + use time_manager_mod, only: set_calendar_type, time_type, increment_date use time_manager_mod, only: set_time, set_date, get_time, get_date, month_name use time_manager_mod, only: GREGORIAN, JULIAN, NOLEAP, THIRTY_DAY_MONTHS, NO_CALENDAR @@ -40,8 +38,7 @@ module MOM_cap_mod use MOM_cap_methods, only: ChkErr #ifdef CESMCOUPLED -use shr_file_mod, only: shr_file_setLogUnit, shr_file_getLogUnit -use shr_mpi_mod, only : shr_mpi_min, shr_mpi_max +use shr_log_mod, only: shr_log_setLogUnit, shr_log_getLogUnit #endif use time_utils_mod, only: esmf2fms_time @@ -80,6 +77,7 @@ module MOM_cap_mod use ESMF, only: ESMF_AlarmGet, ESMF_AlarmIsCreated, ESMF_ALARMLIST_ALL, ESMF_AlarmIsEnabled use ESMF, only: ESMF_STATEITEM_NOTFOUND, ESMF_FieldWrite use ESMF, only: ESMF_END_ABORT, ESMF_Finalize +use ESMF, only: ESMF_REDUCE_MAX, ESMF_REDUCE_MIN, ESMF_VMAllReduce use ESMF, only: operator(==), operator(/=), operator(+), operator(-) ! TODO ESMF_GridCompGetInternalState does not have an explicit Fortran interface. @@ -140,7 +138,6 @@ module MOM_cap_mod logical :: write_diagnostics = .false. logical :: overwrite_timeslice = .false. character(len=32) :: runtype !< run type -integer :: logunit !< stdout logging unit number logical :: profile_memory = .true. logical :: grid_attach_area = .false. logical :: use_coldstart = .true. @@ -489,7 +486,30 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) !$ call omp_set_num_threads(nthrds) - call fms_init(mpi_comm_mom) + ! reset shr logging to my log file + if (localPet==0) then + call NUOPC_CompAttributeGet(gcomp, name="diro", & + isPresent=isPresentDiro, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call NUOPC_CompAttributeGet(gcomp, name="logfile", & + isPresent=isPresentLogfile, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (isPresentDiro .and. isPresentLogfile) then + call NUOPC_CompAttributeGet(gcomp, name="diro", value=diro, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call NUOPC_CompAttributeGet(gcomp, name="logfile", value=logfile, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + open(newunit=stdout,file=trim(diro)//"/"//trim(logfile)) + else + stdout = output_unit + endif + else + stdout = output_unit + endif + call shr_log_setLogUnit(stdout) + + call MOM_infra_init(mpi_comm_mom) + call constants_init call field_manager_init @@ -526,7 +546,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) time_start = set_date (YEAR,MONTH,DAY,HOUR,MINUTE,SECOND) if (is_root_pe()) then - write(logunit,*) subname//'current time: y,m,d-',year,month,day,'h,m,s=',hour,minute,second + write(stdout,*) subname//'current time: y,m,d-',year,month,day,'h,m,s=',hour,minute,second endif ! get start/reference time @@ -538,33 +558,14 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) time0 = set_date (YEAR,MONTH,DAY,HOUR,MINUTE,SECOND) - if (is_root_pe()) then - write(logunit,*) subname//'start time: y,m,d-',year,month,day,'h,m,s=',hour,minute,second - endif ! rsd need to figure out how to get this without share code !call shr_nuopc_get_component_instance(gcomp, inst_suffix, inst_index) !inst_name = "OCN"//trim(inst_suffix) - ! reset shr logging to my log file + if (is_root_pe()) then - call NUOPC_CompAttributeGet(gcomp, name="diro", & - isPresent=isPresentDiro, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call NUOPC_CompAttributeGet(gcomp, name="logfile", & - isPresent=isPresentLogfile, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (isPresentDiro .and. isPresentLogfile) then - call NUOPC_CompAttributeGet(gcomp, name="diro", value=diro, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call NUOPC_CompAttributeGet(gcomp, name="logfile", value=logfile, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - open(newunit=logunit,file=trim(diro)//"/"//trim(logfile)) - else - logunit = output_unit - endif - else - logunit = output_unit + write(stdout,*) subname//'start time: y,m,d-',year,month,day,'h,m,s=',hour,minute,second endif starttype = "" @@ -659,7 +660,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) call ocean_model_init_sfc(ocean_state, ocean_public) - call mpp_get_compute_domain(ocean_public%domain, isc, iec, jsc, jec) + call get_domain_extent(ocean_public%domain, isc, iec, jsc, jec) allocate ( Ice_ocean_boundary% u_flux (isc:iec,jsc:jec), & Ice_ocean_boundary% v_flux (isc:iec,jsc:jec), & @@ -823,7 +824,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) call NUOPC_Advertise(exportState, standardName=fldsFrOcn(n)%stdname, name=fldsFrOcn(n)%shortname, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return enddo - + if(is_root_pe()) write(stdout,*) 'InitializeAdvertise complete' end subroutine InitializeAdvertise !> Called by NUOPC to realize import and export fields. "Realizing" a field @@ -904,6 +905,12 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) real(ESMF_KIND_R8) :: max_med2mod_areacor real(ESMF_KIND_R8) :: min_mod2med_areacor real(ESMF_KIND_R8) :: min_med2mod_areacor + + real(ESMF_KIND_R8) :: min_areacor(2) + real(ESMF_KIND_R8) :: max_areacor(2) + real(ESMF_KIND_R8) :: min_areacor_glob(2) + real(ESMF_KIND_R8) :: max_areacor_glob(2) + real(ESMF_KIND_R8) :: max_mod2med_areacor_glob real(ESMF_KIND_R8) :: max_med2mod_areacor_glob real(ESMF_KIND_R8) :: min_mod2med_areacor_glob @@ -913,7 +920,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) rc = ESMF_SUCCESS - call shr_file_setLogUnit (logunit) + call shr_log_setLogUnit (stdout) !---------------------------------------------------------------------------- ! Get pointers to ocean internal state @@ -1032,7 +1039,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (localPet == 0) then - write(logunit,*)'mesh file for mom6 domain is ',trim(cvalue) + write(stdout,*)'mesh file for mom6 domain is ',trim(cvalue) endif ! recreate the mesh using the above distGrid @@ -1060,7 +1067,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) call ESMF_MeshGet(Emesh, elemMaskArray=elemMaskArray, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call mpp_get_compute_domain(ocean_public%domain, isc, iec, jsc, jec) + call get_domain_extent(ocean_public%domain, isc, iec, jsc, jec) n = 0 do j = jsc, jec jg = j + ocean_grid%jsc - jsc @@ -1148,19 +1155,20 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) deallocate(model_areas) ! Write diagnostic output for correction factors - min_mod2med_areacor = minval(mod2med_areacor) - max_mod2med_areacor = maxval(mod2med_areacor) - min_med2mod_areacor = minval(med2mod_areacor) - max_med2mod_areacor = maxval(med2mod_areacor) - call shr_mpi_max(max_mod2med_areacor, max_mod2med_areacor_glob, mpicom) - call shr_mpi_min(min_mod2med_areacor, min_mod2med_areacor_glob, mpicom) - call shr_mpi_max(max_med2mod_areacor, max_med2mod_areacor_glob, mpicom) - call shr_mpi_min(min_med2mod_areacor, min_med2mod_areacor_glob, mpicom) + min_areacor(1) = minval(mod2med_areacor) + max_areacor(1) = maxval(mod2med_areacor) + min_areacor(2) = minval(med2mod_areacor) + max_areacor(2) = maxval(med2mod_areacor) + call ESMF_VMAllReduce(vm, min_areacor, min_areacor_glob, 2, ESMF_REDUCE_MIN, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMAllReduce(vm, max_areacor, max_areacor_glob, 2, ESMF_REDUCE_MAX, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (localPet == 0) then - write(logunit,'(2A,2g23.15,A )') trim(subname),' : min_mod2med_areacor, max_mod2med_areacor ',& - min_mod2med_areacor_glob, max_mod2med_areacor_glob, 'MOM6' - write(logunit,'(2A,2g23.15,A )') trim(subname),' : min_med2mod_areacor, max_med2mod_areacor ',& - min_med2mod_areacor_glob, max_med2mod_areacor_glob, 'MOM6' + write(stdout,'(2A,2g23.15,A )') trim(subname),' : min_mod2med_areacor, max_mod2med_areacor ',& + min_areacor_glob(1), max_areacor_glob(1), 'MOM6' + write(stdout,'(2A,2g23.15,A )') trim(subname),' : min_med2mod_areacor, max_med2mod_areacor ',& + min_areacor_glob(2), max_areacor_glob(2), 'MOM6' end if #endif @@ -1311,7 +1319,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) ! values for j=0 and wrap-around in i. on tripole seam, decomposition ! domains are 1 larger in j; to load corner values need to loop one extra row - call mpp_get_compute_domain(ocean_public%domain, isc, iec, jsc, jec) + call get_domain_extent(ocean_public%domain, isc, iec, jsc, jec) lbnd1 = lbound(dataPtr_mask,1) ubnd1 = ubound(dataPtr_mask,1) @@ -1568,7 +1576,7 @@ subroutine ModelAdvance(gcomp, rc) rc = ESMF_SUCCESS if(profile_memory) call ESMF_VMLogMemInfo("Entering MOM Model_ADVANCE: ") - call shr_file_setLogUnit (logunit) + call shr_log_setLogUnit (stdout) !$ call omp_set_num_threads(nthrds) @@ -1782,7 +1790,7 @@ subroutine ModelAdvance(gcomp, rc) endif if (is_root_pe()) then - write(logunit,*) subname//' writing restart file ',trim(restartname) + write(stdout,*) subname//' writing restart file ',trim(restartname) endif endif endif ! restart_mode @@ -2039,8 +2047,8 @@ subroutine ocean_model_finalize(gcomp, rc) call ocean_model_end(ocean_public, ocean_State, Time, write_restart=write_restart) call field_manager_end() - call fms_io_exit() - call fms_end() + call io_infra_end() + call MOM_infra_end() write(*,*) 'MOM: --- completed ---' @@ -2253,17 +2261,17 @@ end subroutine fld_list_add #ifndef CESMCOUPLED -subroutine shr_file_setLogUnit(nunit) +subroutine shr_log_setLogUnit(nunit) integer, intent(in) :: nunit ! do nothing for this stub - its just here to replace ! having cppdefs in the main program -end subroutine shr_file_setLogUnit +end subroutine shr_log_setLogUnit -subroutine shr_file_getLogUnit(nunit) +subroutine shr_log_getLogUnit(nunit) integer, intent(in) :: nunit ! do nothing for this stub - its just here to replace ! having cppdefs in the main program -end subroutine shr_file_getLogUnit +end subroutine shr_log_getLogUnit #endif !> @@ -2761,7 +2769,7 @@ end subroutine shr_file_getLogUnit !! with incoming coupling fields from other components. These three derived types are allocated during the !! [InitializeAdvertise] (@ref MOM_cap_mod::initializeadvertise) phase. Also during that !! phase, the `ice_ocean_boundary` type members are all allocated using bounds retrieved -!! from `mpp_get_compute_domain()`. +!! from `get_domain_extent()`. !! !! During the [InitializeRealize] (@ref MOM_cap_mod::initializerealize) phase, !! `ESMF_Field`s are created for each of the coupling fields in the `ice_ocean_boundary` From 7824dcec75baec29402f57714c4ae41550ae385a Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Mon, 12 Dec 2022 12:19:04 -0700 Subject: [PATCH 16/27] switch to openmpi for github tests --- .github/actions/ubuntu-setup/action.yml | 4 ++-- config_src/drivers/nuopc_cap/mom_cap.F90 | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/.github/actions/ubuntu-setup/action.yml b/.github/actions/ubuntu-setup/action.yml index 3fd2ea13cf..3f3ba5f0b6 100644 --- a/.github/actions/ubuntu-setup/action.yml +++ b/.github/actions/ubuntu-setup/action.yml @@ -13,7 +13,7 @@ runs: sudo apt-get install netcdf-bin sudo apt-get install libnetcdf-dev sudo apt-get install libnetcdff-dev - sudo apt-get install mpich - sudo apt-get install libmpich-dev + sudo apt-get install openmpi-bin + sudo apt-get install libopenmpi-dev sudo apt-get install linux-tools-common echo "::endgroup::" diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index f1f2bdced6..7b5bc38cae 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -901,20 +901,10 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) real(ESMF_KIND_R8), allocatable :: mesh_areas(:) real(ESMF_KIND_R8), allocatable :: model_areas(:) real(ESMF_KIND_R8), pointer :: dataPtr_mesh_areas(:) - real(ESMF_KIND_R8) :: max_mod2med_areacor - real(ESMF_KIND_R8) :: max_med2mod_areacor - real(ESMF_KIND_R8) :: min_mod2med_areacor - real(ESMF_KIND_R8) :: min_med2mod_areacor - real(ESMF_KIND_R8) :: min_areacor(2) real(ESMF_KIND_R8) :: max_areacor(2) real(ESMF_KIND_R8) :: min_areacor_glob(2) real(ESMF_KIND_R8) :: max_areacor_glob(2) - - real(ESMF_KIND_R8) :: max_mod2med_areacor_glob - real(ESMF_KIND_R8) :: max_med2mod_areacor_glob - real(ESMF_KIND_R8) :: min_mod2med_areacor_glob - real(ESMF_KIND_R8) :: min_med2mod_areacor_glob character(len=*), parameter :: subname='(MOM_cap:InitializeRealize)' !-------------------------------- From 12238ae219238275ebc75cf6aa7249ba26657dfb Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Mon, 12 Dec 2022 12:39:20 -0700 Subject: [PATCH 17/27] remove whitespace --- config_src/drivers/nuopc_cap/mom_cap.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index 7b5bc38cae..4684b0e6ff 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -507,7 +507,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) stdout = output_unit endif call shr_log_setLogUnit(stdout) - + call MOM_infra_init(mpi_comm_mom) call constants_init From cac67d1e79a7a708881f6101a827cbadf71579e1 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Mon, 12 Dec 2022 12:53:36 -0700 Subject: [PATCH 18/27] revert change to github action --- .github/actions/ubuntu-setup/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/ubuntu-setup/action.yml b/.github/actions/ubuntu-setup/action.yml index 3f3ba5f0b6..3fd2ea13cf 100644 --- a/.github/actions/ubuntu-setup/action.yml +++ b/.github/actions/ubuntu-setup/action.yml @@ -13,7 +13,7 @@ runs: sudo apt-get install netcdf-bin sudo apt-get install libnetcdf-dev sudo apt-get install libnetcdff-dev - sudo apt-get install openmpi-bin - sudo apt-get install libopenmpi-dev + sudo apt-get install mpich + sudo apt-get install libmpich-dev sudo apt-get install linux-tools-common echo "::endgroup::" From 8bc69f67e7437aa13f949f8cff03d3e4c705c96c Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Tue, 13 Dec 2022 13:52:54 -0700 Subject: [PATCH 19/27] further improvement to logunit setting --- config_src/drivers/nuopc_cap/mom_cap.F90 | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index 4684b0e6ff..08f564973b 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -38,7 +38,7 @@ module MOM_cap_mod use MOM_cap_methods, only: ChkErr #ifdef CESMCOUPLED -use shr_log_mod, only: shr_log_setLogUnit, shr_log_getLogUnit +use shr_log_mod, only: shr_log_setLogUnit #endif use time_utils_mod, only: esmf2fms_time @@ -507,7 +507,10 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) stdout = output_unit endif call shr_log_setLogUnit(stdout) - + call NUOPC_CompAttributeAdd(gcomp, (/"logunit"/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call NUOPC_CompAttributeSet(gcomp, "logunit", logunit, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return call MOM_infra_init(mpi_comm_mom) call constants_init @@ -2256,12 +2259,6 @@ subroutine shr_log_setLogUnit(nunit) ! do nothing for this stub - its just here to replace ! having cppdefs in the main program end subroutine shr_log_setLogUnit - -subroutine shr_log_getLogUnit(nunit) - integer, intent(in) :: nunit - ! do nothing for this stub - its just here to replace - ! having cppdefs in the main program -end subroutine shr_log_getLogUnit #endif !> From a789254e0fcbe31f675410507793ca2455f5cbe8 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Tue, 13 Dec 2022 15:09:58 -0700 Subject: [PATCH 20/27] get the variable name correct --- config_src/drivers/nuopc_cap/mom_cap.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index 08f564973b..c909be8652 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -509,7 +509,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) call shr_log_setLogUnit(stdout) call NUOPC_CompAttributeAdd(gcomp, (/"logunit"/), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call NUOPC_CompAttributeSet(gcomp, "logunit", logunit, rc=rc) + call NUOPC_CompAttributeSet(gcomp, "logunit", stdout, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return call MOM_infra_init(mpi_comm_mom) From de8023d108daf91ea3af9036dd1e737876622e6d Mon Sep 17 00:00:00 2001 From: Marshall Ward Date: Thu, 22 Dec 2022 13:09:18 -0500 Subject: [PATCH 21/27] POSIX: siglongjmp and sigsetjmp_missing fixes This patch fixes two issues in the POSIX API. The `siglongjmp` interface was referencing the wrong symbol (`longjmp`). While this did not seem to cause any issues, possibly due to some shared definitions on glibc/BSD platforms, the error was correctly detected by the Cray compiler. This patch corrects the C symbol name. The `sigsetjmp_missing` function, as a default replacement for a missing `sigsetjmp`, was also defined without a return value, since it always returns an error if called at runtime. The Cray compiler raised a warning about this, so we now assign a return value of -1, although it is never used. Thanks to Jim Edwards for reporting these errors. --- src/framework/posix.F90 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/framework/posix.F90 b/src/framework/posix.F90 index 142d7634e2..e5ec0e60d4 100644 --- a/src/framework/posix.F90 +++ b/src/framework/posix.F90 @@ -188,7 +188,7 @@ end subroutine longjmp_posix !> C interface to POSIX siglongjmp() !! Users should use the Fortran-defined siglongjmp() function. - subroutine siglongjmp_posix(env, val) bind(c, name="longjmp") + subroutine siglongjmp_posix(env, val) bind(c, name="siglongjmp") ! #include ! int siglongjmp(jmp_buf env, int val); import :: sigjmp_buf, c_int @@ -360,6 +360,9 @@ function sigsetjmp_missing(env, savesigs) result(rc) bind(c) print '(a)', 'ERROR: sigsetjmp() is not implemented in this build.' print '(a)', 'Recompile with autoconf or -DSIGSETJMP_NAME=\"\".' error stop + + ! NOTE: Compilers may expect a return value, even if it is unreachable + rc = -1 end function sigsetjmp_missing end module posix From 0f1fc0386928b3649fe841cc8a2896015f07a4fe Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Mon, 9 Jan 2023 13:31:41 -0700 Subject: [PATCH 22/27] fix gnu restart issue by removing leading spaces in restartfiles list --- config_src/drivers/nuopc_cap/mom_cap.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index d244205b1b..1abb7c9229 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -625,7 +625,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) endif ocean_public%is_ocean_pe = .true. - call ocean_model_init(ocean_public, ocean_state, time0, time_start, input_restart_file=trim(restartfiles)) + call ocean_model_init(ocean_public, ocean_state, time0, time_start, input_restart_file=trim(adjustl(restartfiles))) ! GMM, this call is not needed in CESM. Check with EMC if it can be deleted. call ocean_model_flux_init(ocean_state) From b693dd2d81a7d4b3de7fc05011d5519e4d6101b8 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Thu, 12 Jan 2023 09:35:09 -0700 Subject: [PATCH 23/27] remove more direct calls to FMS in mom_cap.F90 --- config_src/drivers/nuopc_cap/mom_cap.F90 | 37 ++++++------------------ 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index b9090e9cec..6768a2f547 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -2,26 +2,18 @@ module MOM_cap_mod -use constants_mod, only: constants_init -use diag_manager_mod, only: diag_manager_init, diag_manager_end -use field_manager_mod, only: field_manager_init, field_manager_end -use mom_coms_infra, only: MOM_infra_init, MOM_infra_end -use mom_io_infra, only: io_infra_end -use mom_domain_infra, only: get_domain_extent -use MOM_io, only: stdout +use MOM_domains, only: get_domain_extent +use MOM_io, only: stdout, io_infra_end use mpp_domains_mod, only: mpp_get_compute_domains use mpp_domains_mod, only: mpp_get_ntile_count, mpp_get_pelist, mpp_get_global_domain use mpp_domains_mod, only: mpp_get_domain_npes -use time_manager_mod, only: set_calendar_type, time_type, increment_date -use time_manager_mod, only: set_time, set_date, get_time, get_date, month_name -use time_manager_mod, only: GREGORIAN, JULIAN, NOLEAP, THIRTY_DAY_MONTHS, NO_CALENDAR -use time_manager_mod, only: operator( <= ), operator( < ), operator( >= ) -use time_manager_mod, only: operator( + ), operator( - ), operator( / ) -use time_manager_mod, only: operator( * ), operator( /= ), operator( > ) -use time_manager_mod, only: date_to_string -use time_manager_mod, only: fms_get_calendar_type => get_calendar_type -use MOM_domains, only: MOM_infra_init, num_pes, root_pe, pe_here +use MOM_time_manager, only: set_calendar_type, time_type, set_time, set_date, month_name +use MOM_time_manager, only: GREGORIAN, JULIAN, NOLEAP +use MOM_time_manager, only: operator( <= ), operator( < ), operator( >= ) +use MOM_time_manager, only: operator( + ), operator( - ), operator( / ) +use MOM_time_manager, only: operator( * ), operator( /= ), operator( > ) +use MOM_domains, only: MOM_infra_init, MOM_infra_end, num_pes, root_pe, pe_here use MOM_file_parser, only: get_param, log_version, param_file_type, close_param_file use MOM_get_input, only: get_MOM_input, directories use MOM_domains, only: pass_var @@ -486,9 +478,6 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (chkerr(rc,__LINE__,u_FILE_u)) return call MOM_infra_init(mpi_comm_mom) - call constants_init - call field_manager_init - ! determine the calendar if (cesm_coupled) then call NUOPC_CompAttributeGet(gcomp, name="calendar", value=cvalue, & @@ -514,8 +503,6 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) call set_calendar_type (JULIAN) endif - call diag_manager_init - ! this ocean connector will be driven at set interval DT = set_time (DT_OCEAN, 0) ! get current time @@ -1987,7 +1974,6 @@ subroutine ocean_model_finalize(gcomp, rc) ESMF_LOGMSG_INFO) call ocean_model_end(ocean_public, ocean_State, Time, write_restart=write_restart) - call field_manager_end() call io_infra_end() call MOM_infra_end() @@ -2337,8 +2323,7 @@ end subroutine shr_log_setLogUnit !! @subsection Initialization Initialization !! !! During the [InitializeAdvertise] (@ref MOM_cap_mod::initializeadvertise) phase, calls are -!! made to MOM's native initialization subroutines, including `fms_init()`, `constants_init()`, -!! `field_manager_init()`, `diag_manager_init()`, and `set_calendar_type()`. The MPI communicator +!! made to MOM's native initialization subroutines. The MPI communicator !! is pulled in through the ESMF VM object for the MOM component. The dt and start time are set !! from parameters from the incoming ESMF clock with calls to `set_time()` and `set_date().` !! @@ -2413,10 +2398,6 @@ end subroutine shr_log_setLogUnit !! procedures: !! !! call ocean_model_end (ocean_public, ocean_State, Time) -!! call diag_manager_end(Time ) -!! call field_manager_end -!! call fms_io_exit -!! call fms_end !! !! @section ModelFields Model Fields !! From 4959ee12fcba3ee01b4f91d98076885bf5e1a2ef Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Sun, 15 Jan 2023 20:52:39 -0700 Subject: [PATCH 24/27] update more write units to stdout in mom6 nuopc cap and let only rootpe write logs. --- config_src/drivers/nuopc_cap/mom_cap.F90 | 8 +++++-- .../nuopc_cap/mom_ocean_model_nuopc.F90 | 24 +++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index 6768a2f547..979dc3b25a 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -1948,7 +1948,9 @@ subroutine ocean_model_finalize(gcomp, rc) logical :: write_restart character(len=*),parameter :: subname='(MOM_cap:ocean_model_finalize)' - write(*,*) 'MOM: --- finalize called ---' + if (is_root_pe()) then + write(stdout,*) 'MOM: --- finalize called ---' + endif rc = ESMF_SUCCESS call ESMF_GridCompGetInternalState(gcomp, ocean_internalstate, rc) @@ -1978,7 +1980,9 @@ subroutine ocean_model_finalize(gcomp, rc) call io_infra_end() call MOM_infra_end() - write(*,*) 'MOM: --- completed ---' + if (is_root_pe()) then + write(stdout,*) 'MOM: --- completed ---' + endif end subroutine ocean_model_finalize diff --git a/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 b/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 index 1fb35b31a6..808e6d44d9 100644 --- a/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 +++ b/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 @@ -53,7 +53,7 @@ module MOM_ocean_model_nuopc use MOM_coupler_types, only : coupler_type_set_diags, coupler_type_send_data use mpp_domains_mod, only : domain2d, mpp_get_layout, mpp_get_global_domain use mpp_domains_mod, only : mpp_define_domains, mpp_get_compute_domain, mpp_get_data_domain -use fms_mod, only : stdout +use MOM_io, only : stdout use MOM_EOS, only : gsw_sp_from_sr, gsw_pt_from_ct use MOM_wave_interface, only : wave_parameters_CS, MOM_wave_interface_init use MOM_wave_interface, only : Update_Surface_Waves, query_wave_properties @@ -446,7 +446,7 @@ subroutine ocean_model_init(Ocean_sfc, OS, Time_init, Time_in, gas_fields_ocn, i call diag_mediator_close_registration(OS%diag) if (is_root_pe()) & - write(*,'(/12x,a/)') '======== COMPLETED MOM INITIALIZATION ========' + write(stdout,'(/12x,a/)') '======== COMPLETED MOM INITIALIZATION ========' call callTree_leave("ocean_model_init(") end subroutine ocean_model_init @@ -1123,20 +1123,18 @@ subroutine ocean_public_type_chksum(id, timestep, ocn) ! Local variables integer(kind=int64) :: chks ! A checksum for the field logical :: root ! True only on the root PE - integer :: outunit ! The output unit to write to - outunit = stdout() root = is_root_pe() - if (root) write(outunit,*) "BEGIN CHECKSUM(ocean_type):: ", id, timestep - chks = field_chksum(ocn%t_surf ) ; if (root) write(outunit,100) 'ocean%t_surf ', chks - chks = field_chksum(ocn%s_surf ) ; if (root) write(outunit,100) 'ocean%s_surf ', chks - chks = field_chksum(ocn%u_surf ) ; if (root) write(outunit,100) 'ocean%u_surf ', chks - chks = field_chksum(ocn%v_surf ) ; if (root) write(outunit,100) 'ocean%v_surf ', chks - chks = field_chksum(ocn%sea_lev) ; if (root) write(outunit,100) 'ocean%sea_lev ', chks - chks = field_chksum(ocn%frazil ) ; if (root) write(outunit,100) 'ocean%frazil ', chks - chks = field_chksum(ocn%melt_potential) ; if (root) write(outunit,100) 'ocean%melt_potential ', chks - call coupler_type_write_chksums(ocn%fields, outunit, 'ocean%') + if (root) write(stdout,*) "BEGIN CHECKSUM(ocean_type):: ", id, timestep + chks = field_chksum(ocn%t_surf ) ; if (root) write(stdout,100) 'ocean%t_surf ', chks + chks = field_chksum(ocn%s_surf ) ; if (root) write(stdout,100) 'ocean%s_surf ', chks + chks = field_chksum(ocn%u_surf ) ; if (root) write(stdout,100) 'ocean%u_surf ', chks + chks = field_chksum(ocn%v_surf ) ; if (root) write(stdout,100) 'ocean%v_surf ', chks + chks = field_chksum(ocn%sea_lev) ; if (root) write(stdout,100) 'ocean%sea_lev ', chks + chks = field_chksum(ocn%frazil ) ; if (root) write(stdout,100) 'ocean%frazil ', chks + chks = field_chksum(ocn%melt_potential) ; if (root) write(stdout,100) 'ocean%melt_potential ', chks + call coupler_type_write_chksums(ocn%fields, stdout, 'ocean%') 100 FORMAT(" CHECKSUM::",A20," = ",Z20) end subroutine ocean_public_type_chksum From 774074ff9db66da5434e910ef30a52fdfc376b31 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Mon, 6 Mar 2023 09:51:58 -0700 Subject: [PATCH 25/27] minor styling fixes to address PR #1594 reviews. --- config_src/drivers/nuopc_cap/mom_cap.F90 | 8 +++---- src/tracer/ideal_age_example.F90 | 30 ++++++++++++------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/config_src/drivers/nuopc_cap/mom_cap.F90 b/config_src/drivers/nuopc_cap/mom_cap.F90 index 76d541813e..b7d651bf55 100644 --- a/config_src/drivers/nuopc_cap/mom_cap.F90 +++ b/config_src/drivers/nuopc_cap/mom_cap.F90 @@ -1687,10 +1687,10 @@ subroutine ModelAdvance(gcomp, rc) close(writeunit) endif else ! not cesm_coupled - write(restartname,'(i4.4,2(i2.2),A,3(i2.2),A)') year, month, day,".", hour, minute, seconds, & - ".MOM.res" - write(stoch_restartname,'(i4.4,2(i2.2),A,3(i2.2),A)') year, month, day,".", hour, minute, seconds, & - ".ocn_stoch.res.nc" + write(restartname,'(i4.4,2(i2.2),A,3(i2.2),A)') year, month, day,".", hour, minute, seconds, & + ".MOM.res" + write(stoch_restartname,'(i4.4,2(i2.2),A,3(i2.2),A)') year, month, day,".", hour, minute, seconds, & + ".ocn_stoch.res.nc" call ESMF_LogWrite("MOM_cap: Writing restart : "//trim(restartname), ESMF_LOGMSG_INFO) ! write restart file(s) diff --git a/src/tracer/ideal_age_example.F90 b/src/tracer/ideal_age_example.F90 index e2d557ccb2..f0ad7cab99 100644 --- a/src/tracer/ideal_age_example.F90 +++ b/src/tracer/ideal_age_example.F90 @@ -379,7 +379,7 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, young_val = CS%young_val(m) else young_val = CS%young_val(m) * & - exp((year-CS%tracer_start_year(m)) * CS%growth_rate(m)) + exp((year-CS%tracer_start_year(m)) * CS%growth_rate(m)) endif if (m == CS%BL_residence_num) then @@ -409,11 +409,11 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, do k=nk+2,nz - if (G%mask2dT(i,j) > 0.0) then - CS%tr(i,j,k,m) = young_val - else - CS%tr(i,j,k,m) = CS%land_val(m) - endif + if (G%mask2dT(i,j) > 0.0) then + CS%tr(i,j,k,m) = young_val + else + CS%tr(i,j,k,m) = CS%land_val(m) + endif enddo enddo ; enddo @@ -428,11 +428,11 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, enddo do k=CS%nkbl+1,nz - if (G%mask2dT(i,j) > 0.0) then - CS%tr(i,j,k,m) = young_val - else - CS%tr(i,j,k,m) = CS%land_val(m) - endif + if (G%mask2dT(i,j) > 0.0) then + CS%tr(i,j,k,m) = young_val + else + CS%tr(i,j,k,m) = CS%land_val(m) + endif enddo enddo ; enddo @@ -479,10 +479,10 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, enddo ; enddo ; enddo if (CS%tracer_ages(m) .and. (year>=CS%tracer_start_year(m))) then - !$OMP parallel do default(none) shared(is,ie,js,je,CS,nz,G,dt,Isecs_per_year,m) - do k=CS%nkbl+1,nz ; do j=js,je ; do i=is,ie - CS%tr(i,j,k,m) = CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year - enddo ; enddo ; enddo + !$OMP parallel do default(none) shared(is,ie,js,je,CS,nz,G,dt,Isecs_per_year,m) + do k=CS%nkbl+1,nz ; do j=js,je ; do i=is,ie + CS%tr(i,j,k,m) = CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt*Isecs_per_year + enddo ; enddo ; enddo endif From ed93a232aa019a818a770e35ea53198abe72d7f5 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Mon, 6 Mar 2023 09:58:37 -0700 Subject: [PATCH 26/27] add SMOOTH_RI to MOM_obsolete_params.F90 --- src/diagnostics/MOM_obsolete_params.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/diagnostics/MOM_obsolete_params.F90 b/src/diagnostics/MOM_obsolete_params.F90 index e686261fdf..c44aebf08d 100644 --- a/src/diagnostics/MOM_obsolete_params.F90 +++ b/src/diagnostics/MOM_obsolete_params.F90 @@ -97,6 +97,8 @@ subroutine find_obsolete_params(param_file) ! This parameter is on the to-do list to be obsoleted. ! call obsolete_logical(param_file, "NEW_SPONGES", hint="Use INTERPOLATE_SPONGE_TIME_SPACE instead.") + call obsolete_logical(param_file, "SMOOTH_RI", hint="Instead use N_SMOOTH_RI.") + ! Write the file version number to the model log. call log_version(param_file, mdl, version) From d1d53bcb4c7ebf4263d35ef0420c95a5fb82a579 Mon Sep 17 00:00:00 2001 From: alperaltuntas Date: Thu, 16 Mar 2023 18:31:37 -0600 Subject: [PATCH 27/27] remove inadvertent reassignment of layer_frac --- src/tracer/ideal_age_example.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tracer/ideal_age_example.F90 b/src/tracer/ideal_age_example.F90 index f0ad7cab99..dfa5e894db 100644 --- a/src/tracer/ideal_age_example.F90 +++ b/src/tracer/ideal_age_example.F90 @@ -400,7 +400,6 @@ subroutine ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, if (G%mask2dT(i,j) > 0.0) then layer_frac = BL_layers(i,j)-nk - layer_frac = 0.9 CS%tr(i,j,k,m) = layer_frac * (CS%tr(i,j,k,m) + G%mask2dT(i,j)*dt & *Isecs_per_year) + (1.-layer_frac) * young_val else