Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

log_diag_field_info updates for main #1117

Merged
merged 4 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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