From f3ab52c8b961b33208f9ed9b4d26f968b4c45681 Mon Sep 17 00:00:00 2001 From: Robert Hallberg Date: Sun, 5 Dec 2021 10:01:34 -0500 Subject: [PATCH 1/4] +Remove clocks inside of j-loops Removed clocks that were being called from inside of j-loops in two modules. These are inefficient and can cause the model to hang in some cases if used, and there are better ways to get timing information at this level. If there is interest in the timing breakdown at this level, the code should be restructured to move the key blocks outside of the j-loops. The run-time parameter ALLOW_CLOCKS_IN_OMP_LOOPS is no longer being used so it is now obsoleted. All answers are bitwise identical, but there are changes to some MOM_parameter_doc files. --- src/diagnostics/MOM_obsolete_params.F90 | 1 + .../vertical/MOM_bulk_mixed_layer.F90 | 54 +------------------ .../vertical/MOM_regularize_layers.F90 | 18 +------ 3 files changed, 5 insertions(+), 68 deletions(-) diff --git a/src/diagnostics/MOM_obsolete_params.F90 b/src/diagnostics/MOM_obsolete_params.F90 index 034b87e91b..c579241ffe 100644 --- a/src/diagnostics/MOM_obsolete_params.F90 +++ b/src/diagnostics/MOM_obsolete_params.F90 @@ -87,6 +87,7 @@ subroutine find_obsolete_params(param_file) call obsolete_logical(param_file, "MSTAR_FIXED", hint="Instead use MSTAR_MODE.") call obsolete_logical(param_file, "USE_VISBECK_SLOPE_BUG", .false.) + call obsolete_logical(param_file, "ALLOW_CLOCKS_IN_OMP_LOOPS", .true.) call obsolete_logical(param_file, "LARGE_FILE_SUPPORT", .true.) call obsolete_real(param_file, "MIN_Z_DIAG_INTERVAL") call obsolete_char(param_file, "Z_OUTPUT_GRID_FILE") diff --git a/src/parameterizations/vertical/MOM_bulk_mixed_layer.F90 b/src/parameterizations/vertical/MOM_bulk_mixed_layer.F90 index c80ee0ea61..046329523d 100644 --- a/src/parameterizations/vertical/MOM_bulk_mixed_layer.F90 +++ b/src/parameterizations/vertical/MOM_bulk_mixed_layer.F90 @@ -136,8 +136,6 @@ module MOM_bulk_mixed_layer !! detrainment [R Z L2 T-3 ~> W m-2]. diag_PE_detrain2 !< The spurious source of potential energy due to mixed layer only !! detrainment [R Z L2 T-3 ~> W m-2]. - logical :: allow_clocks_in_omp_loops !< If true, clocks can be called from inside loops that can - !! be threaded. To run with multiple threads, set to False. type(group_pass_type) :: pass_h_sum_hmbl_prev !< For group halo pass !>@{ Diagnostic IDs @@ -150,8 +148,7 @@ module MOM_bulk_mixed_layer end type bulkmixedlayer_CS !>@{ CPU clock IDs -integer :: id_clock_detrain=0, id_clock_mech=0, id_clock_conv=0, id_clock_adjustment=0 -integer :: id_clock_EOS=0, id_clock_resort=0, id_clock_pass=0 +integer :: id_clock_pass=0 !>@} contains @@ -433,7 +430,6 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C d_ea(i,k) = 0.0 ; d_eb(i,k) = 0.0 enddo ; enddo - if (id_clock_EOS>0) call cpu_clock_begin(id_clock_EOS) ! Calculate an estimate of the mid-mixed layer pressure [R L2 T-2 ~> Pa] if (associated(tv%p_surf)) then do i=is,ie ; p_ref(i) = tv%p_surf(i,j) ; enddo @@ -449,27 +445,22 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C call calculate_density(T(:,k), S(:,k), p_ref, R0(:,k), tv%eqn_of_state, EOSdom) call calculate_density(T(:,k), S(:,k), p_ref_cv, Rcv(:,k), tv%eqn_of_state, EOSdom) enddo - if (id_clock_EOS>0) call cpu_clock_end(id_clock_EOS) if (CS%ML_resort) then - if (id_clock_resort>0) call cpu_clock_begin(id_clock_resort) if (CS%ML_presort_nz_conv_adj > 0) & call convective_adjustment(h, u, v, R0, Rcv, T, S, eps, d_eb, dKE_CA, cTKE, j, G, GV, & US, CS, CS%ML_presort_nz_conv_adj) call sort_ML(h, R0, eps, G, GV, CS, ksort) - if (id_clock_resort>0) call cpu_clock_end(id_clock_resort) else do k=1,nz ; do i=is,ie ; ksort(i,k) = k ; enddo ; enddo - if (id_clock_adjustment>0) call cpu_clock_begin(id_clock_adjustment) ! Undergo instantaneous entrainment into the buffer layers and mixed layers ! to remove hydrostatic instabilities. Any water that is lighter than ! currently in the mixed or buffer layer is entrained. call convective_adjustment(h, u, v, R0, Rcv, T, S, eps, d_eb, dKE_CA, cTKE, j, G, GV, US, CS) do i=is,ie ; h_CA(i) = h(i,1) ; enddo - if (id_clock_adjustment>0) call cpu_clock_end(id_clock_adjustment) endif if (associated(fluxes%lrunoff) .and. CS%do_rivermix) then @@ -493,9 +484,6 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C do i=is,ie ; TKE_river(i) = 0.0 ; enddo endif - - if (id_clock_conv>0) call cpu_clock_begin(id_clock_conv) - ! The surface forcing is contained in the fluxes type. ! We aggregate the thermodynamic forcing for a time step into the following: ! netMassInOut = water [H ~> m or kg m-2] added/removed via surface fluxes @@ -515,16 +503,12 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C nsw, Pen_SW_bnd, opacity_band, Conv_En, dKE_FC, & j, ksort, G, GV, US, CS, tv, fluxes, dt, aggregate_FW_forcing) - if (id_clock_conv>0) call cpu_clock_end(id_clock_conv) - ! Now the mixed layer undergoes mechanically forced entrainment. ! The mixed layer may entrain down to the Monin-Obukhov depth if the ! surface is becoming lighter, and is effecti1336vely detraining. ! First the TKE at the depth of free convection that is available ! to drive mixing is calculated. - if (id_clock_mech>0) call cpu_clock_begin(id_clock_mech) - call find_starting_TKE(htot, h_CA, fluxes, Conv_En, cTKE, dKE_FC, dKE_CA, & TKE, TKE_river, Idecay_len_TKE, cMKE, dt, Idt_diag, & j, ksort, G, GV, US, CS) @@ -542,7 +526,6 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C if (CS%TKE_diagnostics) then ; do i=is,ie CS%diag_TKE_mech_decay(i,j) = CS%diag_TKE_mech_decay(i,j) - Idt_diag * TKE(i) enddo ; endif - if (id_clock_mech>0) call cpu_clock_end(id_clock_mech) ! Calculate the homogeneous mixed layer properties and store them in layer 0. do i=is,ie ; if (htot(i) > 0.0) then @@ -572,10 +555,8 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C ! these unused layers (but not currently in the code). if (CS%ML_resort) then - if (id_clock_resort>0) call cpu_clock_begin(id_clock_resort) call resort_ML(h(:,0:), T(:,0:), S(:,0:), R0(:,0:), Rcv(:,0:), GV%Rlay(:), eps, & d_ea, d_eb, ksort, G, GV, CS, dR0_dT, dR0_dS, dRcv_dT, dRcv_dS) - if (id_clock_resort>0) call cpu_clock_end(id_clock_resort) endif if (CS%limit_det .or. (CS%id_Hsfc_max > 0) .or. (CS%id_Hsfc_min > 0)) then @@ -606,7 +587,6 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C ! Move water left in the former mixed layer into the buffer layer and ! from the buffer layer into the interior. These steps might best be ! treated in conjuction. - if (id_clock_detrain>0) call cpu_clock_begin(id_clock_detrain) if (CS%nkbl == 1) then call mixedlayer_detrain_1(h(:,0:), T(:,0:), S(:,0:), R0(:,0:), Rcv(:,0:), & GV%Rlay(:), dt, dt__diag, d_ea, d_eb, j, G, GV, US, CS, & @@ -619,8 +599,6 @@ subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, C ! This code only works with 1 or 2 buffer layers. call MOM_error(FATAL, "MOM_mixed_layer: CS%nkbl must be 1 or 2 for now.") endif - if (id_clock_detrain>0) call cpu_clock_end(id_clock_detrain) - if (CS%id_Hsfc_used > 0) then do i=is,ie ; Hsfc_used(i,j) = GV%H_to_Z * h(i,0) ; enddo @@ -3526,12 +3504,6 @@ subroutine bulkmixedlayer_init(Time, G, GV, US, param_file, diag, CS) "If true, use code with a bug that causes a loss of momentum conservation "//& "during mixedlayer convection.", default=.false.) - call get_param(param_file, mdl, "ALLOW_CLOCKS_IN_OMP_LOOPS", & - CS%allow_clocks_in_omp_loops, & - "If true, clocks can be called from inside loops that can "//& - "be threaded. To run with multiple threads, set to False.", & - default=.true.) - CS%id_ML_depth = register_diag_field('ocean_model', 'h_ML', diag%axesT1, & Time, 'Surface mixed layer depth', 'm') CS%id_TKE_wind = register_diag_field('ocean_model', 'TKE_wind', diag%axesT1, & @@ -3610,30 +3582,8 @@ subroutine bulkmixedlayer_init(Time, G, GV, US, param_file, diag, CS) if (CS%id_PE_detrain2 > 0) call safe_alloc_alloc(CS%diag_PE_detrain2, isd, ied, jsd, jed) if (CS%id_ML_depth > 0) call safe_alloc_alloc(CS%ML_depth, isd, ied, jsd, jed) - if (CS%allow_clocks_in_omp_loops) then - id_clock_detrain = cpu_clock_id('(Ocean mixed layer detrain)', & - sync=.false., grain=CLOCK_ROUTINE) - id_clock_mech = cpu_clock_id('(Ocean mixed layer mechanical entrainment)', & - sync=.false., grain=CLOCK_ROUTINE) - id_clock_conv = cpu_clock_id('(Ocean mixed layer convection)', & - sync=.false., grain=CLOCK_ROUTINE) - if (CS%ML_resort) then - id_clock_resort = cpu_clock_id('(Ocean mixed layer resorting)', & - sync=.false., grain=CLOCK_ROUTINE) - else - id_clock_adjustment = cpu_clock_id('(Ocean mixed layer convective adjustment)', & - sync=.false., grain=CLOCK_ROUTINE) - endif - id_clock_EOS = cpu_clock_id('(Ocean mixed layer EOS)', & - sync=.false., grain=CLOCK_ROUTINE) - endif - if (CS%limit_det .or. (CS%id_Hsfc_min > 0)) & - id_clock_pass = cpu_clock_id('(Ocean mixed layer halo updates)', grain=CLOCK_ROUTINE) - - -! if (CS%limit_det) then -! endif + id_clock_pass = cpu_clock_id('(Ocean mixed layer halo updates)', grain=CLOCK_ROUTINE) end subroutine bulkmixedlayer_init diff --git a/src/parameterizations/vertical/MOM_regularize_layers.F90 b/src/parameterizations/vertical/MOM_regularize_layers.F90 index 868ff6a832..1f141ffd0f 100644 --- a/src/parameterizations/vertical/MOM_regularize_layers.F90 +++ b/src/parameterizations/vertical/MOM_regularize_layers.F90 @@ -56,13 +56,11 @@ module MOM_regularize_layers logical :: debug !< If true, do more thorough checks for debugging purposes. integer :: id_def_rat = -1 !< A diagnostic ID - logical :: allow_clocks_in_omp_loops !< If true, clocks can be called from inside loops that - !! can be threaded. To run with multiple threads, set to False. end type regularize_layers_CS !>@{ Clock IDs !! \todo Should these be global? -integer :: id_clock_pass, id_clock_EOS +integer :: id_clock_pass !>@} contains @@ -233,12 +231,10 @@ subroutine regularize_surface(h, tv, dt, ea, eb, G, GV, US, CS) ! Now restructure the layers. !$OMP parallel do default(private) shared(is,ie,js,je,nz,do_j,def_rat_h,CS,nkmb,G,GV,US, & !$OMP e,I_dtol,h,tv,debug,h_neglect,p_ref_cv,ea, & - !$OMP eb,id_clock_EOS,nkml,EOSdom) + !$OMP eb,nkml,EOSdom) do j=js,je ; if (do_j(j)) then -! call cpu_clock_begin(id_clock_EOS) ! call calculate_density_derivs(T(:,1), S(:,1), p_ref_cv, dRcv_dT, dRcv_dS, tv%eqn_of_state, EOSdom) -! call cpu_clock_end(id_clock_EOS) do k=1,nz ; do i=is,ie ; d_ea(i,k) = 0.0 ; d_eb(i,k) = 0.0 ; enddo ; enddo kmax_d_ea = 0 @@ -367,11 +363,9 @@ subroutine regularize_surface(h, tv, dt, ea, eb, G, GV, US, CS) enddo endif if (det_any) then - call cpu_clock_begin(id_clock_EOS) do k=1,nkmb call calculate_density(T_2d(:,k), S_2d(:,k), p_ref_cv, Rcv(:,k), tv%eqn_of_state, EOSdom) enddo - call cpu_clock_end(id_clock_EOS) do i=is,ie ; if (det_i(i)) then k1 = nkmb ; k2 = nz @@ -780,19 +774,11 @@ subroutine regularize_layers_init(Time, G, GV, param_file, diag, CS) ! call get_param(param_file, mdl, "DEBUG_CONSERVATION", CS%debug, & ! "If true, monitor conservation and extrema.", default=.false., do_not_log=just_read) - call get_param(param_file, mdl, "ALLOW_CLOCKS_IN_OMP_LOOPS", CS%allow_clocks_in_omp_loops, & - "If true, clocks can be called from inside loops that can "//& - "be threaded. To run with multiple threads, set to False.", & - default=.true., do_not_log=just_read) - if (.not.CS%regularize_surface_layers) return CS%id_def_rat = register_diag_field('ocean_model', 'deficit_ratio', diag%axesT1, & Time, 'Max face thickness deficit ratio', 'nondim') - if (CS%allow_clocks_in_omp_loops) then - id_clock_EOS = cpu_clock_id('(Ocean regularize_layers EOS)', grain=CLOCK_ROUTINE) - endif id_clock_pass = cpu_clock_id('(Ocean regularize_layers halo updates)', grain=CLOCK_ROUTINE) end subroutine regularize_layers_init From eecadd2b35b46e8da9b49863a411de8a9f54aa35 Mon Sep 17 00:00:00 2001 From: Robert Hallberg Date: Sun, 5 Dec 2021 10:10:18 -0500 Subject: [PATCH 2/4] Deallocate eta_PF_start to avoid a memory leak Added a deallocate call for eta_PF_start in step_MOM_dyn_split_RK2() to avoid a possible memory leak. All answers are bitwise identical. --- src/core/MOM_dynamics_split_RK2.F90 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core/MOM_dynamics_split_RK2.F90 b/src/core/MOM_dynamics_split_RK2.F90 index d0a324f96f..dd82825d0e 100644 --- a/src/core/MOM_dynamics_split_RK2.F90 +++ b/src/core/MOM_dynamics_split_RK2.F90 @@ -895,11 +895,10 @@ subroutine step_MOM_dyn_split_RK2(u, v, h, tv, visc, Time_local, dt, forces, p_s enddo ; enddo enddo - ! The time-averaged free surface height has already been set by the last - ! call to btstep. + ! The time-averaged free surface height has already been set by the last call to btstep. - ! Deallocate this memory to avoid a memory leak. ###We should also revisit how this array is declared. - RWH - !### if (dyn_p_surf .and. associated(eta_PF_start)) deallocate(eta_PF_start) + ! Deallocate this memory to avoid a memory leak. ### We should revisit how this array is declared. -RWH + if (dyn_p_surf .and. associated(eta_PF_start)) deallocate(eta_PF_start) ! Here various terms used in to update the momentum equations are ! offered for time averaging. From b0963d4923c0f9416eedfb7077a60b1a5545c57c Mon Sep 17 00:00:00 2001 From: Robert Hallberg Date: Sun, 5 Dec 2021 12:25:30 -0500 Subject: [PATCH 3/4] +Set find_salt_root if SHELF_THREE_EQN = .False. Set find_salt_root even if SHELF_THREE_EQN = .False. to avoid using an uninitialized logical to determine which parameters are logged. Without this the contents of some MOM_parameter_doc.all files could depend on the state of uninitialized memory and was compiler dependent in some cases. All answers are bitwise identical, but in some cases the contents of MOM_parameter_doc files could be corrected. --- src/ice_shelf/MOM_ice_shelf.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ice_shelf/MOM_ice_shelf.F90 b/src/ice_shelf/MOM_ice_shelf.F90 index 77166cece0..bbc23bdc5e 100644 --- a/src/ice_shelf/MOM_ice_shelf.F90 +++ b/src/ice_shelf/MOM_ice_shelf.F90 @@ -1409,12 +1409,12 @@ subroutine initialize_ice_shelf(param_file, ocn_grid, Time, CS, diag, forces_in, "If true, user specifies a constant nondimensional heat-transfer coefficient "//& "(GAMMA_T_3EQ), from which the default salt-transfer coefficient is set "//& "as GAMMA_T_3EQ/35. This is used with SHELF_THREE_EQN.", default=.false.) - if (CS%threeeq) then - call get_param(param_file, mdl, "SHELF_S_ROOT", CS%find_salt_root, & + call get_param(param_file, mdl, "SHELF_S_ROOT", CS%find_salt_root, & "If SHELF_S_ROOT = True, salinity at the ice/ocean interface (Sbdry) "//& "is computed from a quadratic equation. Otherwise, the previous "//& - "interactive method to estimate Sbdry is used.", default=.false.) - else + "interactive method to estimate Sbdry is used.", & + default=.false., do_not_log=.not.CS%threeeq) + if (.not.CS%threeeq) then call get_param(param_file, mdl, "SHELF_2EQ_GAMMA_T", CS%gamma_t, & "If SHELF_THREE_EQN is false, this the fixed turbulent "//& "exchange velocity at the ice-ocean interface.", & From f410f3c6093331f9dd54a3eed96e8d6a0c1a418c Mon Sep 17 00:00:00 2001 From: Robert Hallberg Date: Sun, 5 Dec 2021 12:27:34 -0500 Subject: [PATCH 4/4] +Obsolete ETA_TOLERANCE_AUX The runtime parameter ETA_TOLERANCE_AUX was being read but was never used, so it is being obsoleted. However, because some experiments were using this and there are effectively no changes in behavior, a warning will be issued instead of a fatal error if this parameter is set. All answers are bitwise identical, but there are changes to some MOM_parameter_doc files. --- src/core/MOM_continuity_PPM.F90 | 22 +++++----------------- src/diagnostics/MOM_obsolete_params.F90 | 9 +++++++-- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/core/MOM_continuity_PPM.F90 b/src/core/MOM_continuity_PPM.F90 index 4e037998c9..15a6bf72a3 100644 --- a/src/core/MOM_continuity_PPM.F90 +++ b/src/core/MOM_continuity_PPM.F90 @@ -41,10 +41,6 @@ module MOM_continuity_PPM real :: tol_vel !< The tolerance for barotropic velocity !! discrepancies between the barotropic solution and !! the sum of the layer thicknesses [L T-1 ~> m s-1]. - real :: tol_eta_aux !< The tolerance for free-surface height - !! discrepancies between the barotropic solution and - !! the sum of the layer thicknesses when calculating - !! the auxiliary corrected velocities [H ~> m or kg m-2]. real :: CFL_limit_adjust !< The maximum CFL of the adjusted velocities [nondim] logical :: aggress_adjust !< If true, allow the adjusted velocities to have a !! relative CFL change up to 0.5. False by default. @@ -2234,9 +2230,9 @@ subroutine continuity_PPM_init(Time, G, GV, US, param_file, diag, CS) type(diag_ctrl), target, intent(inout) :: diag !< A structure that is used to !! regulate diagnostic output. type(continuity_PPM_CS), intent(inout) :: CS !< Module's control structure. -!> This include declares and sets the variable "version". -#include "version_variable.h" - real :: tol_eta_m ! An unscaled version of tol_eta [m]. + + !> This include declares and sets the variable "version". +# include "version_variable.h" character(len=40) :: mdl = "MOM_continuity_PPM" ! This module's name. CS%initialized = .true. @@ -2267,16 +2263,8 @@ subroutine continuity_PPM_init(Time, G, GV, US, param_file, diag, CS) "tolerance for SSH is 4 times this value. The default "//& "is 0.5*NK*ANGSTROM, and this should not be set less "//& "than about 10^-15*MAXIMUM_DEPTH.", units="m", scale=GV%m_to_H, & - default=0.5*GV%ke*GV%Angstrom_m, unscaled=tol_eta_m) - - !### ETA_TOLERANCE_AUX can be obsoleted. - call get_param(param_file, mdl, "ETA_TOLERANCE_AUX", CS%tol_eta_aux, & - "The tolerance for free-surface height discrepancies "//& - "between the barotropic solution and the sum of the "//& - "layer thicknesses when calculating the auxiliary "//& - "corrected velocities. By default, this is the same as "//& - "ETA_TOLERANCE, but can be made larger for efficiency.", & - units="m", default=tol_eta_m, scale=GV%m_to_H) + default=0.5*GV%ke*GV%Angstrom_m) + call get_param(param_file, mdl, "VELOCITY_TOLERANCE", CS%tol_vel, & "The tolerance for barotropic velocity discrepancies "//& "between the barotropic solution and the sum of the "//& diff --git a/src/diagnostics/MOM_obsolete_params.F90 b/src/diagnostics/MOM_obsolete_params.F90 index c579241ffe..dfadaa1da5 100644 --- a/src/diagnostics/MOM_obsolete_params.F90 +++ b/src/diagnostics/MOM_obsolete_params.F90 @@ -80,6 +80,7 @@ subroutine find_obsolete_params(param_file) "find_obsolete_params: #define DYNAMIC_SURFACE_PRESSURE is not yet "//& "implemented without #define SPLIT.") + call obsolete_real(param_file, "ETA_TOLERANCE_AUX", only_warn=.true.) call obsolete_real(param_file, "BT_MASS_SOURCE_LIMIT", 0.0) call obsolete_int(param_file, "SEAMOUNT_LENGTH_SCALE", hint="Use SEAMOUNT_X_LENGTH_SCALE instead.") @@ -174,21 +175,25 @@ subroutine obsolete_char(param_file, varname, warning_val, hint) end subroutine obsolete_char !> Test for presence of obsolete REAL in parameter file. -subroutine obsolete_real(param_file, varname, warning_val, hint) +subroutine obsolete_real(param_file, varname, warning_val, hint, only_warn) type(param_file_type), intent(in) :: param_file !< Structure containing parameter file data. character(len=*), intent(in) :: varname !< Name of obsolete REAL parameter. real, optional, intent(in) :: warning_val !< An allowed value that causes a warning instead of an error. character(len=*), optional, intent(in) :: hint !< A hint to the user about what to do. + logical, optional, intent(in) :: only_warn !< If present and true, issue warnings instead of fatal errors. + ! Local variables real :: test_val, warn_val + logical :: issue_warning character(len=128) :: hint_msg test_val = -9e35; call read_param(param_file, varname, test_val) warn_val = -9e35; if (present(warning_val)) warn_val = warning_val hint_msg = " " ; if (present(hint)) hint_msg = hint + issue_warning = .false. ; if (present(only_warn)) issue_warning = only_warn if (test_val /= -9e35) then - if (test_val == warn_val) then + if ((test_val == warn_val) .or. issue_warning) then call MOM_ERROR(WARNING, "MOM_obsolete_params: "//trim(varname)// & " is an obsolete run-time flag. "//trim(hint_msg)) else