From 43def16c3869001056f8ae22578bd1af894d019a Mon Sep 17 00:00:00 2001 From: uramirez8707 <49168881+uramirez8707@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:19:33 -0400 Subject: [PATCH] feat: modern diag_manager simplify the diag table yaml (#1545) --- diag_manager/diag_yaml_format.md | 3 + diag_manager/fms_diag_yaml.F90 | 56 +++++++++++++-- test_fms/diag_manager/test_diag_manager2.sh | 78 +++++++++++++++++++++ 3 files changed, 131 insertions(+), 6 deletions(-) diff --git a/diag_manager/diag_yaml_format.md b/diag_manager/diag_yaml_format.md index d8221956d..d9e93c359 100644 --- a/diag_manager/diag_yaml_format.md +++ b/diag_manager/diag_yaml_format.md @@ -100,6 +100,9 @@ Below are some *optional* keys that may be added. - **new_file_freq** is a string that defines the frequency and the frequency units (with a space between the frequency number and units) for closing the existing file - **start_time** is an array of 6 integer indicating when to start the file for the first time. It is in the format [year month day hour minute second]. Requires “new_file_freq” - **filename_time** is the time used to set the name of new files when using new_file_freq. The acceptable values are begin (which will use the begining of the file's time bounds), middle (which will use the middle of the file's time bounds), and end (which will use the end of the file's time bounds). The default is middle +- **reduction** is the reduction method that will be used for all the variables in the file. This is overriden if the reduction is specified at the variable level. The acceptable values are average, diurnalXX (where XX is the number of diurnal samples), powXX (whre XX is the power level), min, max, none, rms, and sum. +- **kind** is a string that defines the type of variable as it will be written out in the file. This is overriden if the kind is specified at the variable level. Acceptable values are r4, r8, i4, and i8. +- **module** is a string that defines the module where the variable is registered in the model code. This is overriden if the module is specified at the variable level. **Example:** The following will create a new file every 6 hours starting at Jan 1 2020. Variable data will be written to the file every 6 hours. diff --git a/diag_manager/fms_diag_yaml.F90 b/diag_manager/fms_diag_yaml.F90 index 5ef49be44..07b012ef6 100644 --- a/diag_manager/fms_diag_yaml.F90 +++ b/diag_manager/fms_diag_yaml.F90 @@ -139,6 +139,15 @@ module fms_diag_yaml_mod !! and values(dim=2) to be !! added as global meta data to !! the file + character (len=:), allocatable :: default_var_precision !< The precision for all of the variables in the file + !! This may be overriden if the precison was defined + !! at the variable level + character (len=:), allocatable :: default_var_reduction !< The reduction for all of the variables in the file + !! This may be overriden if the reduction was defined at + !! the variable level + character (len=:), allocatable :: default_var_module !< The module for all of the variables in the file + !! This may be overriden if the modules was defined at the + !! variable level contains !> All getter functions (functions named get_x(), for member field named x) @@ -468,7 +477,8 @@ subroutine diag_yaml_object_init(diag_subset_output) diag_yaml%diag_fields(var_count)%var_axes_names = "" diag_yaml%diag_fields(var_count)%var_file_is_subregional = diag_yaml%diag_files(file_count)%has_file_sub_region() - call fill_in_diag_fields(diag_yaml_id, var_ids(j), diag_yaml%diag_fields(var_count), allow_averages) + call fill_in_diag_fields(diag_yaml_id, diag_yaml%diag_files(file_count), var_ids(j), & + diag_yaml%diag_fields(var_count), allow_averages) !> Save the variable name in the diag_file type diag_yaml%diag_files(file_count)%file_varlist(file_var_count) = diag_yaml%diag_fields(var_count)%var_varname @@ -604,12 +614,19 @@ subroutine fill_in_diag_files(diag_yaml_id, diag_file_id, yaml_fileobj) &" has multiple global_meta blocks") endif + call diag_get_value_from_key(diag_yaml_id, diag_file_id, "reduction", yaml_fileobj%default_var_reduction, & + is_optional=.true.) + call diag_get_value_from_key(diag_yaml_id, diag_file_id, "kind", yaml_fileobj%default_var_precision, & + is_optional=.true.) + call diag_get_value_from_key(diag_yaml_id, diag_file_id, "module", yaml_fileobj%default_var_module, & + is_optional=.true.) end subroutine !> @brief Fills in a diagYamlFilesVar_type with the contents of a variable block in !! diag_table.yaml -subroutine fill_in_diag_fields(diag_file_id, var_id, field, allow_averages) +subroutine fill_in_diag_fields(diag_file_id, yaml_fileobj, var_id, field, allow_averages) integer, intent(in) :: diag_file_id !< Id of the file block in the yaml file + type(diagYamlFiles_type), intent(in) :: yaml_fileobj !< The yaml file obj for the variables integer, intent(in) :: var_id !< Id of the variable block in the yaml file type(diagYamlFilesVar_type), intent(inout) :: field !< diagYamlFilesVar_type obj to read the contents into logical, intent(in) :: allow_averages !< .True. if averages are allowed for this file @@ -623,8 +640,17 @@ subroutine fill_in_diag_fields(diag_file_id, var_id, field, allow_averages) character(len=:), ALLOCATABLE :: buffer !< buffer to store the reduction method as it is read from the yaml call diag_get_value_from_key(diag_file_id, var_id, "var_name", field%var_varname) - call diag_get_value_from_key(diag_file_id, var_id, "reduction", buffer) + + if (yaml_fileobj%default_var_reduction .eq. "") then + !! If there is no default, the reduction method is required + call diag_get_value_from_key(diag_file_id, var_id, "reduction", buffer) + else + call diag_get_value_from_key(diag_file_id, var_id, "reduction", buffer, is_optional=.true.) + !! If the reduction was not set for the variable, override it with the default + if (trim(buffer) .eq. "") buffer = yaml_fileobj%default_var_reduction + endif call set_field_reduction(field, buffer) + deallocate(buffer) if (.not. allow_averages) then if (field%var_reduction .ne. time_none) & @@ -633,9 +659,27 @@ subroutine fill_in_diag_fields(diag_file_id, var_id, field, allow_averages) "Check your diag_table.yaml for the field:"//trim(field%var_varname)) endif - call diag_get_value_from_key(diag_file_id, var_id, "module", field%var_module) - deallocate(buffer) - call diag_get_value_from_key(diag_file_id, var_id, "kind", buffer) + if (yaml_fileobj%default_var_module .eq. "") then + call diag_get_value_from_key(diag_file_id, var_id, "module", field%var_module) + else + call diag_get_value_from_key(diag_file_id, var_id, "module", buffer, is_optional=.true.) + !! If the module was set for the variable, override it with the default + if (trim(buffer) .eq. "") then + field%var_module = yaml_fileobj%default_var_module + else + field%var_module = trim(buffer) + endif + deallocate(buffer) + endif + + if (yaml_fileobj%default_var_precision .eq. "") then + !! If there is no default, the kind is required + call diag_get_value_from_key(diag_file_id, var_id, "kind", buffer) + else + call diag_get_value_from_key(diag_file_id, var_id, "kind", buffer, is_optional=.true.) + !! If the kind was set for the variable, override it with the default + if (trim(buffer) .eq. "") buffer = yaml_fileobj%default_var_precision + endif call set_field_kind(field, buffer) call diag_get_value_from_key(diag_file_id, var_id, "output_name", field%var_outname, is_optional=.true.) diff --git a/test_fms/diag_manager/test_diag_manager2.sh b/test_fms/diag_manager/test_diag_manager2.sh index 629934b0b..7b280c885 100755 --- a/test_fms/diag_manager/test_diag_manager2.sh +++ b/test_fms/diag_manager/test_diag_manager2.sh @@ -516,6 +516,84 @@ if [ -z "${skipflag}" ]; then title: test_diag_manager base_date: 2 1 1 0 0 0 diag_files: +- file_name: wild_card_name%4yr%2mo%2dy%2hr + filename_time: end + freq: 6 hours + time_units: hours + unlimdim: time + new_file_freq: 6 hours + start_time: 2 1 1 0 0 0 + file_duration: 12 hours + module: test_diag_manager_mod + reduction: average + kind: r4 + varlist: + - var_name: sst + output_name: sst + global_meta: + - is_a_file: true +- file_name: normal + freq: 24 days + time_units: hours + unlimdim: records +# Here the module, kind and reduction are being overwritten with whats on the variable + module: potato_mod + kind: r8 + reduction: min + varlist: + - module: test_diag_manager_mod + var_name: sst + output_name: sst + reduction: average + kind: r4 + write_var: true + attributes: + - do_sst: .true. + sub_region: + - grid_type: latlon + corner1: -80, 0 + corner2: -80, 75 + corner3: -60, 0 + corner4: -60, 75 +- file_name: normal2 + freq: -1 + time_units: hours + unlimdim: records + write_file: true + module: test_diag_manager_mod + reduction: none + kind: r4 + varlist: + - var_name: sstt + output_name: sstt + long_name: S S T + - var_name: sstt2 + output_name: sstt2 + long_name: S S T + write_var: false + sub_region: + - grid_type: index + tile: 1 + corner1: 10, 15 + corner2: 20, 15 + corner3: 10, 25 + corner4: 20, 25 +- file_name: normal3 + freq: -1 + time_units: hours + unlimdim: records + write_file: false +_EOF + +my_test_count=`expr $my_test_count + 1` + test_expect_success "diag_yaml test with the simple diag table.yaml (test $my_test_count)" ' + mpirun -n 1 ../test_diag_yaml + ' + + cat <<_EOF > diag_table.yaml +title: test_diag_manager +base_date: 2 1 1 0 0 0 +diag_files: - file_name: wild_card_name%4yr%2mo%2dy%2hr filename_time: end freq: 6 hours