diff --git a/src/diagnostics/MOM_obsolete_params.F90 b/src/diagnostics/MOM_obsolete_params.F90 index a590ae3893..a0401d7199 100644 --- a/src/diagnostics/MOM_obsolete_params.F90 +++ b/src/diagnostics/MOM_obsolete_params.F90 @@ -168,29 +168,15 @@ subroutine obsolete_logical(param_file, varname, warning_val, hint) character(len=*), optional, intent(in) :: hint !< A hint to the user about what to do. ! Local variables logical :: test_logic, fatal_err + logical :: var_is_set ! True if this value was read by read_param. character(len=128) :: hint_msg - test_logic = .false. ; call read_param(param_file, varname, test_logic) + test_logic = .false. ; call read_param(param_file, varname, test_logic, set=var_is_set) fatal_err = .true. - if (present(warning_val)) fatal_err = (warning_val .neqv. .true.) + if (var_is_set .and. present(warning_val)) fatal_err = (warning_val .neqv. test_logic) hint_msg = " " ; if (present(hint)) hint_msg = hint - if (test_logic) then - if (fatal_err) then - call MOM_ERROR(FATAL, "MOM_obsolete_params: "//trim(varname)// & - " is an obsolete run-time flag, and should not be used. "// & - trim(hint_msg)) - else - call MOM_ERROR(WARNING, "MOM_obsolete_params: "//trim(varname)// & - " is an obsolete run-time flag. "//trim(hint_msg)) - endif - endif - - test_logic = .true. ; call read_param(param_file, varname, test_logic) - fatal_err = .true. - if (present(warning_val)) fatal_err = (warning_val .neqv. .false.) - - if (.not.test_logic) then + if (var_is_set) then if (fatal_err) then call MOM_ERROR(FATAL, "MOM_obsolete_params: "//trim(varname)// & " is an obsolete run-time flag, and should not be used. "// & @@ -211,12 +197,13 @@ subroutine obsolete_char(param_file, varname, warning_val, hint) character(len=*), optional, intent(in) :: hint !< A hint to the user about what to do. ! Local variables character(len=200) :: test_string, hint_msg + logical :: var_is_set ! True if this value was read by read_param. logical :: only_warn - test_string = ''; call read_param(param_file, varname, test_string) + test_string = ''; call read_param(param_file, varname, test_string, set=var_is_set) hint_msg = " " ; if (present(hint)) hint_msg = hint - if (len_trim(test_string) > 0) then + if (var_is_set) then only_warn = .false. if (present(warning_val)) then ! Check if test_string and warning_val are the same. if (len_trim(warning_val) == len_trim(test_string)) then @@ -246,15 +233,16 @@ subroutine obsolete_real(param_file, varname, warning_val, hint, only_warn) ! Local variables real :: test_val, warn_val + logical :: var_is_set ! True if this value was read by read_param. logical :: issue_warning character(len=128) :: hint_msg - test_val = -9e35; call read_param(param_file, varname, test_val) + test_val = -9e35; call read_param(param_file, varname, test_val, set=var_is_set) 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 (var_is_set) 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)) @@ -273,14 +261,15 @@ subroutine obsolete_int(param_file, varname, warning_val, hint) integer, 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. ! Local variables + logical :: var_is_set ! True if this value was read by read_param. integer :: test_val, warn_val character(len=128) :: hint_msg - test_val = -123456788; call read_param(param_file, varname, test_val) + test_val = -123456788; call read_param(param_file, varname, test_val, set=var_is_set) warn_val = -123456788; if (present(warning_val)) warn_val = warning_val hint_msg = " " ; if (present(hint)) hint_msg = hint - if (test_val /= -123456788) then + if (var_is_set) then if (test_val == warn_val) then call MOM_ERROR(WARNING, "MOM_obsolete_params: "//trim(varname)// & " is an obsolete run-time flag. "//trim(hint_msg)) diff --git a/src/framework/MOM_file_parser.F90 b/src/framework/MOM_file_parser.F90 index 7d3337ea24..ba59c93e18 100644 --- a/src/framework/MOM_file_parser.F90 +++ b/src/framework/MOM_file_parser.F90 @@ -8,7 +8,7 @@ module MOM_file_parser use MOM_error_handler, only : MOM_error, FATAL, WARNING, MOM_mesg, assert use MOM_error_handler, only : is_root_pe, stdlog, stdout use MOM_time_manager, only : get_time, time_type, get_ticks_per_second -use MOM_time_manager, only : set_date, get_date, real_to_time, operator(-), set_time +use MOM_time_manager, only : set_date, get_date, real_to_time, operator(-), operator(==), set_time use MOM_document, only : doc_param, doc_module, doc_init, doc_end, doc_type use MOM_document, only : doc_openBlock, doc_closeBlock use MOM_string_functions, only : left_int, left_ints, slasher @@ -618,7 +618,7 @@ function simplifyWhiteSpace(string) end function simplifyWhiteSpace !> This subroutine reads the value of an integer model parameter from a parameter file. -subroutine read_param_int(CS, varname, value, fail_if_missing) +subroutine read_param_int(CS, varname, value, fail_if_missing, set) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: varname !< The case-sensitive name of the parameter to read @@ -626,6 +626,8 @@ subroutine read_param_int(CS, varname, value, fail_if_missing) !! read from the parameter file logical, optional, intent(in) :: fail_if_missing !< If present and true, a fatal error occurs !! if this variable is not found in the parameter file + logical, optional, intent(out) :: set !< If present, this indicates whether this parameter + !! has been found and successfully set in the input files. ! Local variables character(len=CS%max_line_len) :: value_string(1) logical :: found, defined @@ -633,6 +635,7 @@ subroutine read_param_int(CS, varname, value, fail_if_missing) call get_variable_line(CS, varname, found, defined, value_string) if (found .and. defined .and. (LEN_TRIM(value_string(1)) > 0)) then read(value_string(1),*,err = 1001) value + if (present(set)) set = .true. else if (present(fail_if_missing)) then ; if (fail_if_missing) then if (.not.found) then @@ -643,6 +646,7 @@ subroutine read_param_int(CS, varname, value, fail_if_missing) ' found but not set in input files.') endif endif ; endif + if (present(set)) set = .false. endif return 1001 call MOM_error(FATAL,'read_param_int: read error for integer variable '//trim(varname)// & @@ -650,7 +654,7 @@ subroutine read_param_int(CS, varname, value, fail_if_missing) end subroutine read_param_int !> This subroutine reads the values of an array of integer model parameters from a parameter file. -subroutine read_param_int_array(CS, varname, value, fail_if_missing) +subroutine read_param_int_array(CS, varname, value, fail_if_missing, set) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: varname !< The case-sensitive name of the parameter to read @@ -658,12 +662,15 @@ subroutine read_param_int_array(CS, varname, value, fail_if_missing) !! read from the parameter file logical, optional, intent(in) :: fail_if_missing !< If present and true, a fatal error occurs !! if this variable is not found in the parameter file + logical, optional, intent(out) :: set !< If present, this indicates whether this parameter + !! has been found and successfully set in the input files. ! Local variables character(len=CS%max_line_len) :: value_string(1) logical :: found, defined call get_variable_line(CS, varname, found, defined, value_string) if (found .and. defined .and. (LEN_TRIM(value_string(1)) > 0)) then + if (present(set)) set = .true. read(value_string(1),*,end=991,err=1002) value 991 return else @@ -676,6 +683,7 @@ subroutine read_param_int_array(CS, varname, value, fail_if_missing) ' found but not set in input files.') endif endif ; endif + if (present(set)) set = .false. endif return 1002 call MOM_error(FATAL,'read_param_int_array: read error for integer array '//trim(varname)// & @@ -683,7 +691,7 @@ subroutine read_param_int_array(CS, varname, value, fail_if_missing) end subroutine read_param_int_array !> This subroutine reads the value of a real model parameter from a parameter file. -subroutine read_param_real(CS, varname, value, fail_if_missing, scale) +subroutine read_param_real(CS, varname, value, fail_if_missing, scale, set) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: varname !< The case-sensitive name of the parameter to read @@ -693,6 +701,8 @@ subroutine read_param_real(CS, varname, value, fail_if_missing, scale) !! if this variable is not found in the parameter file real, optional, intent(in) :: scale !< A scaling factor that the parameter is multiplied !! by before it is returned. + logical, optional, intent(out) :: set !< If present, this indicates whether this parameter + !! has been found and successfully set in the input files. ! Local variables character(len=CS%max_line_len) :: value_string(1) @@ -702,6 +712,7 @@ subroutine read_param_real(CS, varname, value, fail_if_missing, scale) if (found .and. defined .and. (LEN_TRIM(value_string(1)) > 0)) then read(value_string(1),*,err=1003) value if (present(scale)) value = scale*value + if (present(set)) set = .true. else if (present(fail_if_missing)) then ; if (fail_if_missing) then if (.not.found) then @@ -712,6 +723,7 @@ subroutine read_param_real(CS, varname, value, fail_if_missing, scale) ' found but not set in input files.') endif endif ; endif + if (present(set)) set = .false. endif return 1003 call MOM_error(FATAL,'read_param_real: read error for real variable '//trim(varname)// & @@ -719,7 +731,7 @@ subroutine read_param_real(CS, varname, value, fail_if_missing, scale) end subroutine read_param_real !> This subroutine reads the values of an array of real model parameters from a parameter file. -subroutine read_param_real_array(CS, varname, value, fail_if_missing, scale) +subroutine read_param_real_array(CS, varname, value, fail_if_missing, scale, set) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: varname !< The case-sensitive name of the parameter to read @@ -729,6 +741,8 @@ subroutine read_param_real_array(CS, varname, value, fail_if_missing, scale) !! if this variable is not found in the parameter file real, optional, intent(in) :: scale !< A scaling factor that the parameter is multiplied !! by before it is returned. + logical, optional, intent(out) :: set !< If present, this indicates whether this parameter + !! has been found and successfully set in the input files. ! Local variables character(len=CS%max_line_len) :: value_string(1) @@ -739,7 +753,7 @@ subroutine read_param_real_array(CS, varname, value, fail_if_missing, scale) read(value_string(1),*,end=991,err=1004) value 991 continue if (present(scale)) value(:) = scale*value(:) - return + if (present(set)) set = .true. else if (present(fail_if_missing)) then ; if (fail_if_missing) then if (.not.found) then @@ -750,6 +764,7 @@ subroutine read_param_real_array(CS, varname, value, fail_if_missing, scale) ' found but not set in input files.') endif endif ; endif + if (present(set)) set = .false. endif return 1004 call MOM_error(FATAL,'read_param_real_array: read error for real array '//trim(varname)// & @@ -757,7 +772,7 @@ subroutine read_param_real_array(CS, varname, value, fail_if_missing, scale) end subroutine read_param_real_array !> This subroutine reads the value of a character string model parameter from a parameter file. -subroutine read_param_char(CS, varname, value, fail_if_missing) +subroutine read_param_char(CS, varname, value, fail_if_missing, set) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: varname !< The case-sensitive name of the parameter to read @@ -765,6 +780,8 @@ subroutine read_param_char(CS, varname, value, fail_if_missing) !! read from the parameter file logical, optional, intent(in) :: fail_if_missing !< If present and true, a fatal error occurs !! if this variable is not found in the parameter file + logical, optional, intent(out) :: set !< If present, this indicates whether this parameter + !! has been found and successfully set in the input files. ! Local variables character(len=CS%max_line_len) :: value_string(1) logical :: found, defined @@ -776,10 +793,12 @@ subroutine read_param_char(CS, varname, value, fail_if_missing) call MOM_error(FATAL, 'Unable to find variable '//trim(varname)//' in any input files.') endif ; endif + if (present(set)) set = found + end subroutine read_param_char !> This subroutine reads the values of an array of character string model parameters from a parameter file. -subroutine read_param_char_array(CS, varname, value, fail_if_missing) +subroutine read_param_char_array(CS, varname, value, fail_if_missing, set) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: varname !< The case-sensitive name of the parameter to read @@ -787,6 +806,8 @@ subroutine read_param_char_array(CS, varname, value, fail_if_missing) !! read from the parameter file logical, optional, intent(in) :: fail_if_missing !< If present and true, a fatal error occurs !! if this variable is not found in the parameter file + logical, optional, intent(out) :: set !< If present, this indicates whether this parameter + !! has been found and successfully set in the input files. ! Local variables character(len=CS%max_line_len) :: value_string(1), loc_string @@ -813,10 +834,12 @@ subroutine read_param_char_array(CS, varname, value, fail_if_missing) call MOM_error(FATAL, 'Unable to find variable '//trim(varname)//' in any input files.') endif ; endif + if (present(set)) set = found + end subroutine read_param_char_array !> This subroutine reads the value of a logical model parameter from a parameter file. -subroutine read_param_logical(CS, varname, value, fail_if_missing) +subroutine read_param_logical(CS, varname, value, fail_if_missing, set) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: varname !< The case-sensitive name of the parameter to read @@ -824,6 +847,8 @@ subroutine read_param_logical(CS, varname, value, fail_if_missing) !! read from the parameter file logical, optional, intent(in) :: fail_if_missing !< If present and true, a fatal error occurs !! if this variable is not found in the parameter file + logical, optional, intent(out) :: set !< If present, this indicates whether this parameter + !! has been found and successfully set in the input files. ! Local variables character(len=CS%max_line_len) :: value_string(1) @@ -835,10 +860,13 @@ subroutine read_param_logical(CS, varname, value, fail_if_missing) elseif (present(fail_if_missing)) then ; if (fail_if_missing) then call MOM_error(FATAL, 'Unable to find variable '//trim(varname)//' in any input files.') endif ; endif + + if (present(set)) set = found + end subroutine read_param_logical !> This subroutine reads the value of a time_type model parameter from a parameter file. -subroutine read_param_time(CS, varname, value, timeunit, fail_if_missing, date_format) +subroutine read_param_time(CS, varname, value, timeunit, fail_if_missing, date_format, set) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: varname !< The case-sensitive name of the parameter to read @@ -850,6 +878,8 @@ subroutine read_param_time(CS, varname, value, timeunit, fail_if_missing, date_f logical, optional, intent(out) :: date_format !< If present, this indicates whether this !! parameter was read in a date format, so that it can !! later be logged in the same format. + logical, optional, intent(out) :: set !< If present, this indicates whether this parameter + !! has been found and successfully set in the input files. ! Local variables character(len=CS%max_line_len) :: value_string(1) @@ -891,6 +921,7 @@ subroutine read_param_time(CS, varname, value, timeunit, fail_if_missing, date_f read( value_string(1), *) real_time value = real_to_time(real_time*time_unit) endif + if (present(set)) set = .true. else if (present(fail_if_missing)) then ; if (fail_if_missing) then if (.not.found) then @@ -899,6 +930,7 @@ subroutine read_param_time(CS, varname, value, timeunit, fail_if_missing, date_f call MOM_error(FATAL, 'Variable '//trim(varname)//' found but not set in input files.') endif endif ; endif + if (present(set)) set = .false. endif return @@ -1704,7 +1736,7 @@ end function convert_date_to_string !! and logs it in documentation files. subroutine get_param_int(CS, modulename, varname, value, desc, units, & default, fail_if_missing, do_not_read, do_not_log, & - layoutParam, debuggingParam) + layoutParam, debuggingParam, old_name) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: modulename !< The name of the calling module @@ -1725,15 +1757,34 @@ subroutine get_param_int(CS, modulename, varname, value, desc, units, & !! logged in the layout parameter file logical, optional, intent(in) :: debuggingParam !< If present and true, this parameter is !! logged in the debugging parameter file + character(len=*), optional, intent(in) :: old_name !< A case-sensitive archaic name of the parameter + !! to read. Errors or warnings are issued if the old name + !! is being used. + ! Local variables logical :: do_read, do_log + logical :: fatal_absence, new_name_used, old_name_used, same_value + integer :: old_name_value ! The value that is set when the old name is used. do_read = .true. ; if (present(do_not_read)) do_read = .not.do_not_read do_log = .true. ; if (present(do_not_log)) do_log = .not.do_not_log if (do_read) then if (present(default)) value = default - call read_param_int(CS, varname, value, fail_if_missing) + if (present(old_name)) then + old_name_value = value + call read_param_int(CS, old_name, old_name_value, set=old_name_used) + fatal_absence = .false. ; if ((.not.old_name_used) .and. present(fail_if_missing)) fatal_absence = fail_if_missing + call read_param_int(CS, varname, value, fatal_absence, set=new_name_used) + + ! Issue appropriate warnings or error messages. + same_value = (new_name_used .and. old_name_used .and. (value == old_name_value)) + if (old_name_used) call archaic_param_name_message(varname, old_name, new_name_used, same_value) + + if (old_name_used .and. .not.new_name_used) value = old_name_value + else + call read_param_int(CS, varname, value, fail_if_missing) + endif endif if (do_log) then @@ -1747,7 +1798,7 @@ end subroutine get_param_int !! and logs them in documentation files. subroutine get_param_int_array(CS, modulename, varname, value, desc, units, & default, defaults, fail_if_missing, do_not_read, do_not_log, & - layoutParam, debuggingParam) + layoutParam, debuggingParam, old_name) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: modulename !< The name of the calling module @@ -1769,8 +1820,15 @@ subroutine get_param_int_array(CS, modulename, varname, value, desc, units, & !! logged in the layout parameter file logical, optional, intent(in) :: debuggingParam !< If present and true, this parameter is !! logged in the debugging parameter file + character(len=*), optional, intent(in) :: old_name !< A case-sensitive archaic name of the parameter + !! to read. Errors or warnings are issued if the old name + !! is being used. + ! Local variables logical :: do_read, do_log + logical :: fatal_absence, new_name_used, old_name_used, same_value + integer :: old_name_value(size(value)) ! The values that are set when the old name is used. + integer :: m do_read = .true. ; if (present(do_not_read)) do_read = .not.do_not_read do_log = .true. ; if (present(do_not_log)) do_log = .not.do_not_log @@ -1785,7 +1843,21 @@ subroutine get_param_int_array(CS, modulename, varname, value, desc, units, & if (do_read) then if (present(default)) value(:) = default if (present(defaults)) value(:) = defaults(:) - call read_param_int_array(CS, varname, value, fail_if_missing) + if (present(old_name)) then + old_name_value(:) = value(:) + call read_param_int_array(CS, old_name, old_name_value, set=old_name_used) + fatal_absence = .false. ; if ((.not.old_name_used) .and. present(fail_if_missing)) fatal_absence = fail_if_missing + call read_param_int_array(CS, varname, value, fatal_absence, set=new_name_used) + + ! Issue appropriate warnings or error messages. + same_value = (new_name_used .and. old_name_used) + do m=1,size(value) ; if (value(m) /= old_name_value(m)) same_value = .false. ; enddo + if (old_name_used) call archaic_param_name_message(varname, old_name, new_name_used, same_value) + + if (old_name_used .and. .not.new_name_used) value(:) = old_name_value(:) + else + call read_param_int_array(CS, varname, value, fail_if_missing) + endif endif if (do_log) then @@ -1799,7 +1871,7 @@ end subroutine get_param_int_array !! and logs it in documentation files. subroutine get_param_real(CS, modulename, varname, value, desc, units, & default, fail_if_missing, do_not_read, do_not_log, & - debuggingParam, scale, unscaled) + debuggingParam, scale, unscaled, old_name) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: modulename !< The name of the calling module @@ -1822,15 +1894,34 @@ subroutine get_param_real(CS, modulename, varname, value, desc, units, & !! multiplied by before it is returned. real, optional, intent(out) :: unscaled !< The value of the parameter that would be !! returned without any multiplication by a scaling factor. + character(len=*), optional, intent(in) :: old_name !< A case-sensitive archaic name of the parameter + !! to read. Errors or warnings are issued if the old name + !! is being used. + ! Local variables logical :: do_read, do_log + logical :: fatal_absence, new_name_used, old_name_used, same_value + real :: old_name_value ! The value that is set when the old name is used. do_read = .true. ; if (present(do_not_read)) do_read = .not.do_not_read do_log = .true. ; if (present(do_not_log)) do_log = .not.do_not_log if (do_read) then if (present(default)) value = default - call read_param_real(CS, varname, value, fail_if_missing) + if (present(old_name)) then + old_name_value = value + call read_param_real(CS, old_name, old_name_value, set=old_name_used) + fatal_absence = .false. ; if ((.not.old_name_used) .and. present(fail_if_missing)) fatal_absence = fail_if_missing + call read_param_real(CS, varname, value, fatal_absence, set=new_name_used) + + ! Issue appropriate warnings or error messages. + same_value = (new_name_used .and. old_name_used .and. (value == old_name_value)) + if (old_name_used) call archaic_param_name_message(varname, old_name, new_name_used, same_value) + + if (old_name_used .and. .not.new_name_used) value = old_name_value + else + call read_param_real(CS, varname, value, fail_if_missing) + endif endif if (do_log) then @@ -1847,7 +1938,7 @@ end subroutine get_param_real !! and logs them in documentation files. subroutine get_param_real_array(CS, modulename, varname, value, desc, units, & default, defaults, fail_if_missing, do_not_read, do_not_log, debuggingParam, & - scale, unscaled) + scale, unscaled, old_name) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: modulename !< The name of the calling module @@ -1871,8 +1962,15 @@ subroutine get_param_real_array(CS, modulename, varname, value, desc, units, & !! multiplied by before it is returned. real, dimension(:), optional, intent(out) :: unscaled !< The value of the parameter that would be !! returned without any multiplication by a scaling factor. + character(len=*), optional, intent(in) :: old_name !< A case-sensitive archaic name of the parameter + !! to read. Errors or warnings are issued if the old name + !! is being used. + ! Local variables logical :: do_read, do_log + logical :: fatal_absence, new_name_used, old_name_used, same_value + real :: old_name_value(size(value)) ! The values that are set when the old name is used. + integer :: m do_read = .true. ; if (present(do_not_read)) do_read = .not.do_not_read do_log = .true. ; if (present(do_not_log)) do_log = .not.do_not_log @@ -1887,7 +1985,21 @@ subroutine get_param_real_array(CS, modulename, varname, value, desc, units, & if (do_read) then if (present(default)) value(:) = default if (present(defaults)) value(:) = defaults(:) - call read_param_real_array(CS, varname, value, fail_if_missing) + if (present(old_name)) then + old_name_value(:) = value(:) + call read_param_real_array(CS, old_name, old_name_value, set=old_name_used) + fatal_absence = .false. ; if ((.not.old_name_used) .and. present(fail_if_missing)) fatal_absence = fail_if_missing + call read_param_real_array(CS, varname, value, fatal_absence, set=new_name_used) + + ! Issue appropriate warnings or error messages. + same_value = (new_name_used .and. old_name_used) + do m=1,size(value) ; if (value(m) /= old_name_value(m)) same_value = .false. ; enddo + if (old_name_used) call archaic_param_name_message(varname, old_name, new_name_used, same_value) + + if (old_name_used .and. .not.new_name_used) value(:) = old_name_value(:) + else + call read_param_real_array(CS, varname, value, fail_if_missing) + endif endif if (do_log) then @@ -1904,7 +2016,7 @@ end subroutine get_param_real_array !! and logs it in documentation files. subroutine get_param_char(CS, modulename, varname, value, desc, units, & default, fail_if_missing, do_not_read, do_not_log, & - layoutParam, debuggingParam) + layoutParam, debuggingParam, old_name) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: modulename !< The name of the calling module @@ -1925,15 +2037,34 @@ subroutine get_param_char(CS, modulename, varname, value, desc, units, & !! logged in the layout parameter file logical, optional, intent(in) :: debuggingParam !< If present and true, this parameter is !! logged in the debugging parameter file + character(len=*), optional, intent(in) :: old_name !< A case-sensitive archaic name of the parameter + !! to read. Errors or warnings are issued if the old name + !! is being used. + ! Local variables logical :: do_read, do_log + logical :: fatal_absence, new_name_used, old_name_used, same_value + character(len=:), allocatable :: old_name_value ! The value that is set when the old name is used. do_read = .true. ; if (present(do_not_read)) do_read = .not.do_not_read do_log = .true. ; if (present(do_not_log)) do_log = .not.do_not_log if (do_read) then if (present(default)) value = default - call read_param_char(CS, varname, value, fail_if_missing) + if (present(old_name)) then + old_name_value = value + call read_param_char(CS, old_name, old_name_value, set=old_name_used) + fatal_absence = .false. ; if ((.not.old_name_used) .and. present(fail_if_missing)) fatal_absence = fail_if_missing + call read_param_char(CS, varname, value, fatal_absence, set=new_name_used) + + ! Issue appropriate warnings or error messages. + same_value = (new_name_used .and. old_name_used .and. (trim(value) == trim(old_name_value))) + if (old_name_used) call archaic_param_name_message(varname, old_name, new_name_used, same_value) + + if (old_name_used .and. .not.new_name_used) value = old_name_value + else + call read_param_char(CS, varname, value, fail_if_missing) + endif endif if (do_log) then @@ -1946,7 +2077,7 @@ end subroutine get_param_char !> This subroutine reads the values of an array of character string model parameters !! from a parameter file and logs them in documentation files. subroutine get_param_char_array(CS, modulename, varname, value, desc, units, & - default, fail_if_missing, do_not_read, do_not_log) + default, fail_if_missing, do_not_read, do_not_log, old_name) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: modulename !< The name of the calling module @@ -1963,18 +2094,37 @@ subroutine get_param_char_array(CS, modulename, varname, value, desc, units, & !! value for this parameter, although it might be logged. logical, optional, intent(in) :: do_not_log !< If present and true, do not log this !! parameter to the documentation files + character(len=*), optional, intent(in) :: old_name !< A case-sensitive archaic name of the parameter + !! to read. Errors or warnings are issued if the old name + !! is being used. ! Local variables logical :: do_read, do_log - integer :: i, len_tot, len_val + logical :: fatal_absence, new_name_used, old_name_used, same_value + integer :: i, m, len_tot, len_val character(len=:), allocatable :: cat_val + character(len=:), allocatable :: old_name_value(:) ! The value that is set when the old name is used. do_read = .true. ; if (present(do_not_read)) do_read = .not.do_not_read do_log = .true. ; if (present(do_not_log)) do_log = .not.do_not_log if (do_read) then if (present(default)) value(:) = default - call read_param_char_array(CS, varname, value, fail_if_missing) + if (present(old_name)) then + old_name_value(:) = value(:) + call read_param_char_array(CS, old_name, old_name_value, set=old_name_used) + fatal_absence = .false. ; if ((.not.old_name_used) .and. present(fail_if_missing)) fatal_absence = fail_if_missing + call read_param_char_array(CS, varname, value, fatal_absence, set=new_name_used) + + ! Issue appropriate warnings or error messages. + same_value = (new_name_used .and. old_name_used) + do m=1,size(value) ; if (trim(value(m)) /= trim(old_name_value(m))) same_value = .false. ; enddo + if (old_name_used) call archaic_param_name_message(varname, old_name, new_name_used, same_value) + + if (old_name_used .and. .not.new_name_used) value(:) = old_name_value(:) + else + call read_param_char_array(CS, varname, value, fail_if_missing) + endif endif if (do_log) then @@ -1996,7 +2146,7 @@ end subroutine get_param_char_array !! and logs it in documentation files. subroutine get_param_logical(CS, modulename, varname, value, desc, units, & default, fail_if_missing, do_not_read, do_not_log, & - layoutParam, debuggingParam) + layoutParam, debuggingParam, old_name) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: modulename !< The name of the calling module @@ -2017,15 +2167,35 @@ subroutine get_param_logical(CS, modulename, varname, value, desc, units, & !! logged in the layout parameter file logical, optional, intent(in) :: debuggingParam !< If present and true, this parameter is !! logged in the debugging parameter file + character(len=*), optional, intent(in) :: old_name !< A case-sensitive archaic name of the parameter + !! to read. Errors or warnings are issued if the old name + !! is being used. + ! Local variables logical :: do_read, do_log + logical :: fatal_absence, new_name_used, old_name_used, same_value + logical :: old_name_value ! The value that is set when the old name is used. do_read = .true. ; if (present(do_not_read)) do_read = .not.do_not_read do_log = .true. ; if (present(do_not_log)) do_log = .not.do_not_log if (do_read) then if (present(default)) value = default - call read_param_logical(CS, varname, value, fail_if_missing) + + if (present(old_name)) then + old_name_value = value + call read_param_logical(CS, old_name, old_name_value, set=old_name_used) + fatal_absence = .false. ; if ((.not.old_name_used) .and. present(fail_if_missing)) fatal_absence = fail_if_missing + call read_param_logical(CS, varname, value, fatal_absence, set=new_name_used) + + ! Issue appropriate warnings or error messages. + same_value = (new_name_used .and. old_name_used .and. (value .eqv. old_name_value)) + if (old_name_used) call archaic_param_name_message(varname, old_name, new_name_used, same_value) + + if (old_name_used .and. .not.new_name_used) value = old_name_value + else + call read_param_logical(CS, varname, value, fail_if_missing) + endif endif if (do_log) then @@ -2040,7 +2210,7 @@ end subroutine get_param_logical subroutine get_param_time(CS, modulename, varname, value, desc, units, & default, fail_if_missing, do_not_read, do_not_log, & timeunit, layoutParam, debuggingParam, & - log_as_date) + log_as_date, old_name) type(param_file_type), intent(in) :: CS !< The control structure for the file_parser module, !! it is also a structure to parse for run-time parameters character(len=*), intent(in) :: modulename !< The name of the calling module @@ -2065,8 +2235,14 @@ subroutine get_param_time(CS, modulename, varname, value, desc, units, & !! logged in the debugging parameter file logical, optional, intent(in) :: log_as_date !< If true, log the time_type in date !! format. The default is false. + character(len=*), optional, intent(in) :: old_name !< A case-sensitive archaic name of the parameter + !! to read. Errors or warnings are issued if the old name + !! is being used. + ! Local variables logical :: do_read, do_log, log_date + logical :: fatal_absence, new_name_used, old_name_used, same_value + type(time_type) :: old_name_value ! The value that is set when the old name is used. do_read = .true. ; if (present(do_not_read)) do_read = .not.do_not_read do_log = .true. ; if (present(do_not_log)) do_log = .not.do_not_log @@ -2074,7 +2250,20 @@ subroutine get_param_time(CS, modulename, varname, value, desc, units, & if (do_read) then if (present(default)) value = default - call read_param_time(CS, varname, value, timeunit, fail_if_missing, date_format=log_date) + if (present(old_name)) then + old_name_value = value + call read_param_time(CS, old_name, old_name_value, timeunit, date_format=log_date, set=old_name_used) + fatal_absence = .false. ; if ((.not.old_name_used) .and. present(fail_if_missing)) fatal_absence = fail_if_missing + call read_param_time(CS, varname, value, timeunit, fatal_absence, date_format=log_date, set=new_name_used) + + ! Issue appropriate warnings or error messages. + same_value = (new_name_used .and. old_name_used .and. (value == old_name_value)) + if (old_name_used) call archaic_param_name_message(varname, old_name, new_name_used, same_value) + + if (old_name_used .and. .not.new_name_used) value = old_name_value + else + call read_param_time(CS, varname, value, timeunit, fail_if_missing, date_format=log_date) + endif endif if (do_log) then @@ -2086,6 +2275,28 @@ subroutine get_param_time(CS, modulename, varname, value, desc, units, & end subroutine get_param_time +!> Issue error messages or warnings about the use of an archaic parameter name. +subroutine archaic_param_name_message(varname, old_name, new_name_used, same_value) + character(len=*), intent(in) :: varname !< The case-sensitive name of the parameter to read + character(len=*), intent(in) :: old_name !< The case-sensitive archaic name of the parameter + logical, intent(in) :: new_name_used !< True if varname is used in the parameter file. + logical, intent(in) :: same_value !< True if varname and old_name give the same values. + + if (new_name_used .and. same_value) then + call MOM_error(WARNING, "The runtime parameter "//trim(varname)//& + " is also being set consistently via its older name of "//trim(old_name)//& + ". Please migrate to only using "//trim(varname)//".") + elseif (new_name_used .and. .not.same_value) then + call MOM_error(FATAL, "The runtime parameter "//trim(varname)//& + " is also being set inconsistently via its older name of "//trim(old_name)//& + ". Only use "//trim(varname)//".") + else + call MOM_error(WARNING, "The runtime parameter "//trim(varname)//& + " is being set via its soon to be obsolete name of "//trim(old_name)//& + ". Please migrate to using "//trim(varname)//".") + endif +end subroutine archaic_param_name_message + ! ----------------------------------------------------------------------------- !> Resets the parameter block name to blank