From f0e8cab3d8e58195f7c2663b84fd0bed12fa8b64 Mon Sep 17 00:00:00 2001
From: Ryan Mulhall <35538242+rem1776@users.noreply.github.com>
Date: Tue, 14 Feb 2023 08:51:17 -0500
Subject: [PATCH] feat: log_diag_field_info updates from diag rewrite (#1117)
---
diag_manager/diag_manager.F90 | 110 ++++++++++++++++++----------------
diag_manager/diag_util.F90 | 95 +++++++++++++----------------
2 files changed, 102 insertions(+), 103 deletions(-)
diff --git a/diag_manager/diag_manager.F90 b/diag_manager/diag_manager.F90
index 01f0ad6f8b..c726b109f3 100644
--- a/diag_manager/diag_manager.F90
+++ b/diag_manager/diag_manager.F90
@@ -201,9 +201,6 @@ MODULE diag_manager_mod
! The values are defined as GLO_REG_VAL (-999) and GLO_REG_VAL_ALT
! (-1) in diag_data_mod.
!
- !
- ! Set to true, diag_manager uses mpp_io. Default is fms2_io.
- !
!
USE time_manager_mod, ONLY: set_time, set_date, get_time, time_type, OPERATOR(>=), OPERATOR(>),&
@@ -216,12 +213,12 @@ MODULE diag_manager_mod
USE fms_mod, ONLY: error_mesg, FATAL, WARNING, NOTE, stdout, stdlog, write_version_number,&
& fms_error_handler, check_nml_error, lowercase
USE diag_axis_mod, ONLY: diag_axis_init, get_axis_length, get_axis_num, get_domain2d, get_tile_count,&
- & diag_axis_add_attribute, axis_compatible_check, CENTER, NORTH, EAST
+ & diag_axis_add_attribute, axis_compatible_check, CENTER, NORTH, EAST, get_diag_axis_name
USE diag_util_mod, ONLY: get_subfield_size, log_diag_field_info, update_bounds,&
& check_out_of_bounds, check_bounds_are_exact_dynamic, check_bounds_are_exact_static,&
& diag_time_inc, find_input_field, init_input_field, init_output_field,&
& diag_data_out, write_static, get_date_dif, get_subfield_vert_size, sync_file_times,&
- & prepend_attribute, attribute_init, diag_util_init
+ & prepend_attribute, attribute_init, diag_util_init, field_log_separator
USE diag_data_mod, ONLY: max_files, CMOR_MISSING_VALUE, DIAG_OTHER, DIAG_OCEAN, DIAG_ALL, EVERY_TIME,&
& END_OF_RUN, DIAG_SECONDS, DIAG_MINUTES, DIAG_HOURS, DIAG_DAYS, DIAG_MONTHS, DIAG_YEARS, num_files,&
& max_input_fields, max_output_fields, num_output_fields, EMPTY, FILL_VALUE, null_axis_id,&
@@ -378,17 +375,19 @@ MODULE diag_manager_mod
INTEGER FUNCTION register_diag_field_scalar(module_name, field_name, init_time, &
& long_name, units, missing_value, range, standard_name, do_not_log, err_msg,&
& area, volume, realm)
- CHARACTER(len=*), INTENT(in) :: module_name, field_name
- TYPE(time_type), OPTIONAL, INTENT(in) :: init_time
- CHARACTER(len=*), OPTIONAL, INTENT(in) :: long_name, units, standard_name
- CLASS(*), OPTIONAL, INTENT(in) :: missing_value
- CLASS(*), DIMENSION(:), OPTIONAL, INTENT(in) :: range
- LOGICAL, OPTIONAL, INTENT(in) :: do_not_log !< if TRUE, field information is not logged
- CHARACTER(len=*), OPTIONAL, INTENT(out):: err_msg
- INTEGER, OPTIONAL, INTENT(in) :: area, volume
- CHARACTER(len=*), OPTIONAL, INTENT(in):: realm !< String to set as the value to the modeling_realm attribute
-
- IF ( PRESENT(err_msg) ) err_msg = ''
+ CHARACTER(len=*), INTENT(in) :: module_name !< Module where the field comes from
+ CHARACTER(len=*), INTENT(in) :: field_name !< Name of the field
+ TYPE(time_type), OPTIONAL, INTENT(in) :: init_time !< Time to start writing data from
+ CHARACTER(len=*), OPTIONAL, INTENT(in) :: long_name !< Long_name to add as a variable attribute
+ CHARACTER(len=*), OPTIONAL, INTENT(in) :: units !< Units to add as a variable_attribute
+ CHARACTER(len=*), OPTIONAL, INTENT(in) :: standard_name !< Standard_name to name the variable in the file
+ CLASS(*), OPTIONAL, INTENT(in) :: missing_value !< Missing value to add as a variable attribute
+ CLASS(*), OPTIONAL, INTENT(in) :: range(:) !< Range to add a variable attribute
+ LOGICAL, OPTIONAL, INTENT(in) :: do_not_log !< If TRUE, field information is not logged
+ CHARACTER(len=*), OPTIONAL, INTENT(out):: err_msg !< Error_msg from call
+ INTEGER, OPTIONAL, INTENT(in) :: area !< Id of the area field
+ INTEGER, OPTIONAL, INTENT(in) :: volume !< Id of the volume field
+ CHARACTER(len=*), OPTIONAL, INTENT(in) :: realm !< String to set as the modeling_realm attribute
! Fatal error if range is present and its extent is not 2.
IF ( PRESENT(range) ) THEN
@@ -415,23 +414,27 @@ END FUNCTION register_diag_field_scalar
INTEGER FUNCTION register_diag_field_array(module_name, field_name, axes, init_time, &
& long_name, units, missing_value, range, mask_variant, standard_name, verbose,&
& do_not_log, err_msg, interp_method, tile_count, area, volume, realm)
- CHARACTER(len=*), INTENT(in) :: module_name, field_name
- INTEGER, INTENT(in) :: axes(:)
- TYPE(time_type), INTENT(in) :: init_time
- CHARACTER(len=*), OPTIONAL, INTENT(in) :: long_name, units, standard_name
- CLASS(*), OPTIONAL, INTENT(in) :: missing_value
- CLASS(*), DIMENSION(:), OPTIONAL, INTENT(in) :: range
- LOGICAL, OPTIONAL, INTENT(in) :: mask_variant,verbose
- LOGICAL, OPTIONAL, INTENT(in) :: do_not_log !< if TRUE, field info is not logged
- CHARACTER(len=*), OPTIONAL, INTENT(out):: err_msg
+ CHARACTER(len=*), INTENT(in) :: module_name !< Module where the field comes from
+ CHARACTER(len=*), INTENT(in) :: field_name !< Name of the field
+ INTEGER, INTENT(in) :: axes(:) !< Ids corresponding to the variable axis
+ TYPE(time_type), OPTIONAL, INTENT(in) :: init_time !< Time to start writing data from
+ CHARACTER(len=*), OPTIONAL, INTENT(in) :: long_name !< Long_name to add as a variable attribute
+ CHARACTER(len=*), OPTIONAL, INTENT(in) :: units !< Units to add as a variable_attribute
+ CLASS(*), OPTIONAL, INTENT(in) :: missing_value !< Missing value to add as a variable attribute
+ CLASS(*), OPTIONAL, INTENT(in) :: range(:) !< Range to add a variable attribute
+ LOGICAL, OPTIONAL, INTENT(in) :: mask_variant !< Mask variant
+ CHARACTER(len=*), OPTIONAL, INTENT(in) :: standard_name !< Standard_name to name the variable in the file
+ LOGICAL, OPTIONAL, INTENT(in) :: verbose !< Print more information
+ LOGICAL, OPTIONAL, INTENT(in) :: do_not_log !< If TRUE, field information is not logged
+ CHARACTER(len=*), OPTIONAL, INTENT(out):: err_msg !< Error_msg from call
CHARACTER(len=*), OPTIONAL, INTENT(in) :: interp_method !< The interp method to be used when
!! regridding the field in post-processing.
!! Valid options are "conserve_order1",
!! "conserve_order2", and "none".
- INTEGER, OPTIONAL, INTENT(in) :: tile_count
- INTEGER, OPTIONAL, INTENT(in) :: area !< diag_field_id containing the cell area field
- INTEGER, OPTIONAL, INTENT(in) :: volume !< diag_field_id containing the cell volume field
- CHARACTER(len=*), OPTIONAL, INTENT(in):: realm !< String to set as the value to the modeling_realm attribute
+ INTEGER, OPTIONAL, INTENT(in) :: tile_count !< The current tile number
+ INTEGER, OPTIONAL, INTENT(in) :: area !< Id of the area field
+ INTEGER, OPTIONAL, INTENT(in) :: volume !< Id of the volume field
+ CHARACTER(len=*), OPTIONAL, INTENT(in) :: realm !< String to set as the modeling_realm attribute
INTEGER :: field, j, ind, file_num, freq
INTEGER :: output_units
@@ -634,7 +637,8 @@ INTEGER FUNCTION register_static_field(module_name, field_name, axes, long_name,
INTEGER :: tile, file_num
LOGICAL :: mask_variant1, dynamic1, allow_log
CHARACTER(len=128) :: msg
- INTEGER :: domain_type
+ INTEGER :: domain_type, i
+ character(len=256) :: axes_list, axis_name
! Fatal error if the module has not been initialized.
IF ( .NOT.module_is_initialized ) THEN
@@ -691,12 +695,16 @@ INTEGER FUNCTION register_static_field(module_name, field_name, axes, long_name,
END IF
END IF
- ! Namelist do_diag_field_log is by default false. Thus to log the
- ! registration of the data field, but the OPTIONAL parameter
- ! do_not_log == .FALSE. and the namelist variable
- ! do_diag_field_log == .TRUE..
+ ! only writes log if do_diag_field_log is true in the namelist (default false)
+ ! if do_diag_field_log is true and do_not_log arg is present as well, it will only print if do_not_log = false
IF ( do_diag_field_log.AND.allow_log ) THEN
- CALL log_diag_field_info (module_name, field_name, axes, &
+ axes_list=''
+ DO i = 1, SIZE(axes)
+ CALL get_diag_axis_name(axes(i),axis_name)
+ IF ( TRIM(axes_list) /= '' ) axes_list = TRIM(axes_list)//','
+ axes_list = TRIM(axes_list)//TRIM(axis_name)
+ END DO
+ CALL log_diag_field_info (module_name, field_name, axes, axes_list, &
& long_name, units, missing_value=missing_value, range=range, &
& DYNAMIC=dynamic1)
END IF
@@ -1094,9 +1102,9 @@ INTEGER FUNCTION get_diag_field_id(module_name, field_name)
CHARACTER(len=*), INTENT(in) :: module_name !< Module name that registered the variable
CHARACTER(len=*), INTENT(in) :: field_name !< Variable name
- ! find_input_field will return DIAG_FIELD_NOT_FOUND if the field is not
- ! included in the diag_table
- get_diag_field_id = find_input_field(module_name, field_name, tile_count=1)
+ ! find_input_field will return DIAG_FIELD_NOT_FOUND if the field is not
+ ! included in the diag_table
+ get_diag_field_id = find_input_field(module_name, field_name, tile_count=1)
END FUNCTION get_diag_field_id
!> @brief Finds the corresponding related output field and file for a given input field
@@ -3645,7 +3653,6 @@ SUBROUTINE diag_manager_init(diag_model_subset, time_init, err_msg)
INTEGER, DIMENSION(6), OPTIONAL, INTENT(IN) :: time_init !< Model time diag_manager initialized
CHARACTER(len=*), INTENT(out), OPTIONAL :: err_msg
- CHARACTER(len=*), PARAMETER :: SEP = '|'
INTEGER, PARAMETER :: FltKind = R4_KIND
INTEGER, PARAMETER :: DblKind = R8_KIND
@@ -3660,7 +3667,7 @@ SUBROUTINE diag_manager_init(diag_model_subset, time_init, err_msg)
& max_input_fields, max_axes, do_diag_field_log, write_bytes_in_file, debug_diag_manager,&
& max_num_axis_sets, max_files, use_cmor, issue_oor_warnings,&
& oor_warnings_fatal, max_out_per_in_field, flush_nc_files, region_out_use_alt_value, max_field_attributes,&
- & max_file_attributes, max_axis_attributes, prepend_date, use_mpp_io
+ & max_file_attributes, max_axis_attributes, prepend_date, use_mpp_io, field_log_separator
! If the module was already initialized do nothing
IF ( module_is_initialized ) RETURN
@@ -3755,9 +3762,9 @@ SUBROUTINE diag_manager_init(diag_model_subset, time_init, err_msg)
ALLOCATE(fileobj(max_files))
ALLOCATE(fileobjND(max_files))
ALLOCATE(fnum_for_domain(max_files))
- !> Initialize fnum_for_domain with "dn" which stands for done
+ !> Initialize fnum_for_domain with "dn" which stands for done
fnum_for_domain(:) = "dn"
- CALL error_mesg('diag_manager_mod::diag_manager_init',&
+ CALL error_mesg('diag_manager_mod::diag_manager_init',&
& 'diag_manager is using fms2_io', NOTE)
else
CALL error_mesg('diag_manager_mod::diag_manager_init',&
@@ -3780,23 +3787,24 @@ SUBROUTINE diag_manager_init(diag_model_subset, time_init, err_msg)
END IF
END IF
- CALL parse_diag_table(DIAG_SUBSET=diag_subset_output, ISTAT=mystat, ERR_MSG=err_msg_local)
- IF ( mystat /= 0 ) THEN
+ CALL parse_diag_table(DIAG_SUBSET=diag_subset_output, ISTAT=mystat, ERR_MSG=err_msg_local)
+ IF ( mystat /= 0 ) THEN
IF ( fms_error_handler('diag_manager_mod::diag_manager_init',&
& 'Error parsing diag_table. '//TRIM(err_msg_local), err_msg) ) RETURN
- END IF
+ END IF
!initialize files%bytes_written to zero
files(:)%bytes_written = 0
! open diag field log file
IF ( do_diag_field_log.AND.mpp_pe().EQ.mpp_root_pe() ) THEN
- open(newunit=diag_log_unit, file='diag_field_log.out', action='WRITE')
- WRITE (diag_log_unit,'(777a)') &
- & 'Module', SEP, 'Field', SEP, 'Long Name', SEP,&
- & 'Units', SEP, 'Number of Axis', SEP, 'Time Axis', SEP,&
- & 'Missing Value', SEP, 'Min Value', SEP, 'Max Value', SEP,&
- & 'AXES LIST'
+ open(newunit=diag_log_unit, file='diag_field_log.out', action='WRITE')
+ WRITE (diag_log_unit,'(777a)') &
+ & 'Module', FIELD_LOG_SEPARATOR, 'Field', FIELD_LOG_SEPARATOR, &
+ & 'Long Name', FIELD_LOG_SEPARATOR, 'Units', FIELD_LOG_SEPARATOR, &
+ & 'Number of Axis', FIELD_LOG_SEPARATOR, 'Time Axis', FIELD_LOG_SEPARATOR, &
+ & 'Missing Value', FIELD_LOG_SEPARATOR, 'Min Value', FIELD_LOG_SEPARATOR, &
+ & 'Max Value', FIELD_LOG_SEPARATOR, 'AXES LIST'
END IF
module_is_initialized = .TRUE.
diff --git a/diag_manager/diag_util.F90 b/diag_manager/diag_util.F90
index a676fefede..ad9e9ef0ab 100644
--- a/diag_manager/diag_util.F90
+++ b/diag_manager/diag_util.F90
@@ -106,6 +106,9 @@ MODULE diag_util_mod
LOGICAL :: module_initialized = .FALSE.
+ character(len=1), public :: field_log_separator = '|' !< separator used for csv-style log of registered fields
+ !! set by nml in diag_manager init
+
CONTAINS
@@ -621,11 +624,12 @@ END FUNCTION get_index
!! code uses a do_not_log parameter in the registration calls,
!! and subsequently calls this subroutine to log field information
!! under a generic name.
- SUBROUTINE log_diag_field_info(module_name, field_name, axes, long_name, units,&
- & missing_value, range, dynamic)
+ SUBROUTINE log_diag_field_info(module_name, field_name, axes, axes_list, long_name, units,&
+ & missing_value, range, dynamic )
CHARACTER(len=*), INTENT(in) :: module_name !< Module name
CHARACTER(len=*), INTENT(in) :: field_name !< Field name
INTEGER, DIMENSION(:), INTENT(in) :: axes !< Axis IDs
+ CHARACTER(len=*), INTENT(in) :: axes_list !< Comma seperated list of axes names
CHARACTER(len=*), OPTIONAL, INTENT(in) :: long_name !< Long name for field.
CHARACTER(len=*), OPTIONAL, INTENT(in) :: units !< Unit of field.
CLASS(*), OPTIONAL, INTENT(in) :: missing_value !< Missing value value.
@@ -636,99 +640,86 @@ SUBROUTINE log_diag_field_info(module_name, field_name, axes, long_name, units,&
CHARACTER(len=256) :: lmodule, lfield, lname, lunits
CHARACTER(len=64) :: lmissval, lmin, lmax
CHARACTER(len=8) :: numaxis, timeaxis
- CHARACTER(len=1) :: sep = '|'
- CHARACTER(len=256) :: axis_name, axes_list
INTEGER :: i
REAL :: missing_value_use !< Local copy of missing_value
REAL, DIMENSION(2) :: range_use !< Local copy of range
-
- IF ( .NOT.do_diag_field_log ) RETURN
IF ( mpp_pe().NE.mpp_root_pe() ) RETURN
! Fatal error if range is present and its extent is not 2.
IF ( PRESENT(range) ) THEN
- IF ( SIZE(range) .NE. 2 ) THEN
- ! extent of range should be 2
- CALL error_mesg ('diag_util_mod::log_diag_field_info', 'extent of range should be 2', FATAL)
- END IF
+ IF ( SIZE(range) .NE. 2 ) THEN
+ CALL error_mesg('diag_util_mod::fms_log_field_info', 'extent of range should be 2', FATAL)
+ END IF
END IF
lmodule = TRIM(module_name)
lfield = TRIM(field_name)
IF ( PRESENT(long_name) ) THEN
- lname = TRIM(long_name)
+ lname = TRIM(long_name)
ELSE
- lname = ''
+ lname = ''
END IF
IF ( PRESENT(units) ) THEN
- lunits = TRIM(units)
+ lunits = TRIM(units)
ELSE
- lunits = ''
+ lunits = ''
END IF
WRITE (numaxis,'(i1)') SIZE(axes)
IF (PRESENT(missing_value)) THEN
- IF ( use_cmor ) THEN
- WRITE (lmissval,*) CMOR_MISSING_VALUE
- ELSE
- SELECT TYPE (missing_value)
+ IF ( use_cmor ) THEN
+ WRITE (lmissval,*) CMOR_MISSING_VALUE
+ ELSE
+ SELECT TYPE (missing_value)
TYPE IS (real(kind=r4_kind))
- missing_value_use = missing_value
+ missing_value_use = missing_value
TYPE IS (real(kind=r8_kind))
- missing_value_use = real(missing_value)
+ missing_value_use = real(missing_value)
CLASS DEFAULT
- CALL error_mesg ('diag_util_mod::log_diag_field_info',&
- & 'The missing_value is not one of the supported types of real(kind=4) or real(kind=8)', FATAL)
- END SELECT
- WRITE (lmissval,*) missing_value_use
- END IF
+ CALL error_mesg ('diag_util_mod::log_diag_field_info',&
+ & 'The missing_value is not one of the supported types of real(kind=4) or real(kind=8)', FATAL)
+ END SELECT
+ WRITE (lmissval,*) missing_value_use
+ END IF
ELSE
- lmissval = ''
+ lmissval = ''
ENDIF
IF ( PRESENT(range) ) THEN
- SELECT TYPE (range)
- TYPE IS (real(kind=r4_kind))
+ SELECT TYPE (range)
+ TYPE IS (real(kind=r4_kind))
range_use = range
- TYPE IS (real(kind=r8_kind))
+ TYPE IS (real(kind=r8_kind))
range_use = real(range)
- CLASS DEFAULT
+ CLASS DEFAULT
CALL error_mesg ('diag_util_mod::log_diag_field_info',&
- & 'The range is not one of the supported types of real(kind=4) or real(kind=8)', FATAL)
- END SELECT
- WRITE (lmin,*) range_use(1)
- WRITE (lmax,*) range_use(2)
+ & 'The range is not one of the supported types of real(kind=4) or real(kind=8)', FATAL)
+ END SELECT
+ WRITE (lmin,*) range_use(1)
+ WRITE (lmax,*) range_use(2)
ELSE
- lmin = ''
- lmax = ''
+ lmin = ''
+ lmax = ''
END IF
IF ( PRESENT(dynamic) ) THEN
- IF (dynamic) THEN
+ IF (dynamic) THEN
timeaxis = 'T'
- ELSE
+ ELSE
timeaxis = 'F'
- END IF
+ END IF
ELSE
- timeaxis = ''
+ timeaxis = ''
END IF
- axes_list=''
- DO i = 1, SIZE(axes)
- CALL get_diag_axis_name(axes(i),axis_name)
- IF ( TRIM(axes_list) /= '' ) axes_list = TRIM(axes_list)//','
- axes_list = TRIM(axes_list)//TRIM(axis_name)
- END DO
-
- !write (diag_log_unit,'(8(a,a),a)') &
WRITE (diag_log_unit,'(777a)') &
- & TRIM(lmodule), sep, TRIM(lfield), sep, TRIM(lname), sep,&
- & TRIM(lunits), sep, TRIM(numaxis), sep, TRIM(timeaxis), sep,&
- & TRIM(lmissval), sep, TRIM(lmin), sep, TRIM(lmax), sep,&
- & TRIM(axes_list)
+ & TRIM(lmodule), field_log_separator, TRIM(lfield), field_log_separator, TRIM(lname), field_log_separator,&
+ & TRIM(lunits), field_log_separator, TRIM(numaxis), field_log_separator, TRIM(timeaxis), field_log_separator,&
+ & TRIM(lmissval), field_log_separator, TRIM(lmin), field_log_separator, TRIM(lmax), field_log_separator,&
+ & TRIM(axes_list)
END SUBROUTINE log_diag_field_info
!> @brief Update the output_fields x, y, and z min and max boundaries (array indices).