Skip to content

Commit

Permalink
feat: log_diag_field_info updates from diag rewrite (#1117)
Browse files Browse the repository at this point in the history
  • Loading branch information
rem1776 authored Feb 14, 2023
1 parent 15df841 commit f0e8cab
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 103 deletions.
110 changes: 59 additions & 51 deletions diag_manager/diag_manager.F90
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,6 @@ MODULE diag_manager_mod
! The values are defined as <TT>GLO_REG_VAL</TT> (-999) and <TT>GLO_REG_VAL_ALT</TT>
! (-1) in <TT>diag_data_mod</TT>.
! </DATA>
! <DATA NAME="use_mpp_io" TYPE="LOGICAL" DEFAULT=".false.">
! Set to true, diag_manager uses mpp_io. Default is fms2_io.
! </DATA>
! </NAMELIST>

USE time_manager_mod, ONLY: set_time, set_date, get_time, time_type, OPERATOR(>=), OPERATOR(>),&
Expand All @@ -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,&
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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',&
Expand All @@ -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.
Expand Down
95 changes: 43 additions & 52 deletions diag_manager/diag_util.F90
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.
Expand All @@ -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
! <ERROR STATUS="FATAL">extent of range should be 2</ERROR>
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 <TT>output_fields</TT> x, y, and z min and max boundaries (array indices).
Expand Down

0 comments on commit f0e8cab

Please sign in to comment.