From c1355278e696067e69fbc19ff57cb89d8c5b6c2a Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Mon, 3 Feb 2025 15:56:17 +0000 Subject: [PATCH 01/15] Work in progress --- scripts/ccpp_suite.py | 3 +- test/var_compatibility_test/CMakeLists.txt | 2 +- .../var_compatibility_test/module_rad_ddt.F90 | 28 ++++++++++++ .../module_rad_ddt.meta | 45 +++++++++++++++++++ test/var_compatibility_test/rad_lw.F90 | 35 +++++++++++++++ test/var_compatibility_test/rad_lw.meta | 35 +++++++++++++++ test/var_compatibility_test/rad_sw.F90 | 35 +++++++++++++++ test/var_compatibility_test/rad_sw.meta | 35 +++++++++++++++ test/var_compatibility_test/run_test | 14 ++++-- test/var_compatibility_test/test_host.F90 | 18 +++++--- .../var_compatibility_test/test_host_data.F90 | 16 ++++++- .../test_host_data.meta | 21 +++++++++ test/var_compatibility_test/test_reports.py | 13 ++++-- .../var_compatibility_files.txt | 3 ++ .../var_compatibility_suite.xml | 4 +- 15 files changed, 290 insertions(+), 17 deletions(-) create mode 100644 test/var_compatibility_test/module_rad_ddt.F90 create mode 100644 test/var_compatibility_test/module_rad_ddt.meta create mode 100644 test/var_compatibility_test/rad_lw.F90 create mode 100644 test/var_compatibility_test/rad_lw.meta create mode 100644 test/var_compatibility_test/rad_sw.F90 create mode 100644 test/var_compatibility_test/rad_sw.meta diff --git a/scripts/ccpp_suite.py b/scripts/ccpp_suite.py index d2634c89..c1e13736 100644 --- a/scripts/ccpp_suite.py +++ b/scripts/ccpp_suite.py @@ -657,7 +657,8 @@ def __init__(self, sdfs, host_model, scheme_headers, run_env): self.__ddt_lib = DDTLibrary('{}_api'.format(self.host_model.name), run_env, ddts=all_ddts) for header in [d for d in scheme_headers if d.header_type != 'ddt']: - if header.header_type != 'scheme': + # DJS2024: Schemes and modules with DDTs? + if header.header_type != 'scheme' and header.header_type != 'module': errmsg = "{} is an unknown CCPP API metadata header type, {}" raise CCPPError(errmsg.format(header.title, header.header_type)) # end if diff --git a/test/var_compatibility_test/CMakeLists.txt b/test/var_compatibility_test/CMakeLists.txt index 8cbd7e44..e25f3fda 100644 --- a/test/var_compatibility_test/CMakeLists.txt +++ b/test/var_compatibility_test/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(CCPP_ROOT "${TEST_ROOT}" DIRECTORY) # #------------------------------------------------------------------------------ LIST(APPEND SCHEME_FILES "var_compatibility_files.txt") -LIST(APPEND HOST_FILES "test_host_data" "test_host_mod") +LIST(APPEND HOST_FILES "module_rad_ddt" "test_host_data" "test_host_mod") LIST(APPEND SUITE_FILES "var_compatibility_suite.xml") # HOST is the name of the executable we will build. # We assume there are files ${HOST}.meta and ${HOST}.F90 in CMAKE_SOURCE_DIR diff --git a/test/var_compatibility_test/module_rad_ddt.F90 b/test/var_compatibility_test/module_rad_ddt.F90 new file mode 100644 index 00000000..79ec12a5 --- /dev/null +++ b/test/var_compatibility_test/module_rad_ddt.F90 @@ -0,0 +1,28 @@ +module mod_rad_ddt + USE ccpp_kinds, ONLY: kind_phys + implicit none + + public ty_rad_lw, ty_rad_sw + + !> \section arg_table_module_rad_ddt Argument Table + !! \htmlinclude arg_table_module_rad_ddt.html + !! + + !> \section arg_table_ty_rad_lw Argument Table + !! \htmlinclude arg_table_ty_rad_lw.html + !! + type ty_rad_lw + real(kind_phys) :: sfc_up_lw + real(kind_phys) :: sfc_down_lw + end type ty_rad_lw + + !> \section arg_table_ty_rad_sw Argument Table + !! \htmlinclude arg_table_ty_rad_sw.html + !! + type ty_rad_sw + real(kind_phys) :: sfc_up_sw + real(kind_phys) :: sfc_down_sw + end type ty_rad_sw + +end module mod_rad_ddt + diff --git a/test/var_compatibility_test/module_rad_ddt.meta b/test/var_compatibility_test/module_rad_ddt.meta new file mode 100644 index 00000000..f47c70e4 --- /dev/null +++ b/test/var_compatibility_test/module_rad_ddt.meta @@ -0,0 +1,45 @@ +[ccpp-table-properties] + name = mod_rad_ddt + type = module +[ccpp-arg-table] + name = mod_rad_ddt + type = module + +[ccpp-table-properties] + name = ty_rad_lw + type = ddt + dependencies = +[ccpp-arg-table] + name = ty_rad_lw + type = ddt +[ sfc_up_lw ] + standard_name = surface_upwelling_longwave_radiation_flux + units = W m2 + dimensions = () + type = real + kind = kind_phys +[ sfc_down_lw ] + standard_name = surface_downwelling_longwave_radiation_flux + units = W m2 + dimensions = () + type = real + kind = kind_phys + +[ccpp-table-properties] + name = ty_rad_sw + type = ddt +[ccpp-arg-table] + name = ty_rad_sw + type = ddt +[ sfc_up_sw ] + standard_name = surface_upwelling_shortwave_radiation_flux + units = W m2 + dimensions = () + type = real + kind = kind_phys +[ sfc_down_sw ] + standard_name = surface_downwelling_shortwave_radiation_flux + units = W m2 + dimensions = () + type = real + kind = kind_phys \ No newline at end of file diff --git a/test/var_compatibility_test/rad_lw.F90 b/test/var_compatibility_test/rad_lw.F90 new file mode 100644 index 00000000..6fd97ec8 --- /dev/null +++ b/test/var_compatibility_test/rad_lw.F90 @@ -0,0 +1,35 @@ +module rad_lw + use ccpp_kinds, only: kind_phys + use module_rad_ddt, only: ty_rad_lw + + implicit none + private + + public :: rad_lw_run + +contains + + !> \section arg_table_rad_lw_run Argument Table + !! \htmlinclude arg_table_rad_lw_run.html + !! + subroutine rad_lw_run(ncol, fluxLW, errmsg, errflg) + + integer, intent(in) :: ncol + type(ty_rad_lw), intent(inout) :: fluxLW(:) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + ! Locals + integer :: icol + + errmsg = '' + errflg = 0 + + do icol=1,ncol + fluxLW(icol)%sfc_up_lw = 300._kind_phys + fluxLW(icol)%sfc_down_lw = 50._kind_phys + enddo + + end subroutine rad_lw_run + +end module rad_lw diff --git a/test/var_compatibility_test/rad_lw.meta b/test/var_compatibility_test/rad_lw.meta new file mode 100644 index 00000000..883edf1b --- /dev/null +++ b/test/var_compatibility_test/rad_lw.meta @@ -0,0 +1,35 @@ +[ccpp-table-properties] + name = rad_lw + type = scheme + dependencies = module_rad_ddt.F90 +[ccpp-arg-table] + name = rad_lw_run + type = scheme +[ ncol ] + standard_name = horizontal_loop_extent + type = integer + units = count + dimensions = () + intent = in +[fluxLW] + standard_name = longwave_radiation_fluxes + long_name = longwave radiation fluxes + units = W m-2 + dimensions = (horizontal_loop_extent) + type = ty_rad_lw + intent = inout +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + dimensions = () + type = character + kind = len=512 + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + dimensions = () + type = integer + intent = out diff --git a/test/var_compatibility_test/rad_sw.F90 b/test/var_compatibility_test/rad_sw.F90 new file mode 100644 index 00000000..4354193d --- /dev/null +++ b/test/var_compatibility_test/rad_sw.F90 @@ -0,0 +1,35 @@ +module rad_sw + use ccpp_kinds, only: kind_phys + use module_rad_ddt, only: ty_rad_sw + + implicit none + private + + public :: rad_sw_run + +contains + + !> \section arg_table_rad_sw_run Argument Table + !! \htmlinclude arg_table_rad_sw_run.html + !! + subroutine rad_sw_run(ncol, fluxSW, errmsg, errflg) + + integer, intent(in) :: ncol + type(ty_rad_sw), intent(inout) :: fluxSW(:) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + ! Locals + integer :: icol + + errmsg = '' + errflg = 0 + + do icol=1,ncol + fluxSW(icol)%sfc_up_sw = 100._kind_phys + fluxSW(icol)%sfc_down_sw = 400._kind_phys + enddo + + end subroutine rad_sw_run + +end module rad_sw diff --git a/test/var_compatibility_test/rad_sw.meta b/test/var_compatibility_test/rad_sw.meta new file mode 100644 index 00000000..81f2d583 --- /dev/null +++ b/test/var_compatibility_test/rad_sw.meta @@ -0,0 +1,35 @@ +[ccpp-table-properties] + name = rad_sw + type = scheme + dependencies = module_rad_ddt.F90 +[ccpp-arg-table] + name = rad_sw_run + type = scheme +[ ncol ] + standard_name = horizontal_loop_extent + type = integer + units = count + dimensions = () + intent = in +[fluxSW] + standard_name = shortwave_radiation_fluxes + long_name = shortwave radiation fluxes + units = W m-2 + dimensions = (horizontal_loop_extent) + type = ty_rad_sw + intent = inout +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + dimensions = () + type = character + kind = len=512 + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + dimensions = () + type = integer + intent = out diff --git a/test/var_compatibility_test/run_test b/test/var_compatibility_test/run_test index 5a1d6b5c..8128540e 100755 --- a/test/var_compatibility_test/run_test +++ b/test/var_compatibility_test/run_test @@ -127,8 +127,8 @@ ccpp_files="${utility_files}" ccpp_files="${ccpp_files},${build_dir}/ccpp/test_host_ccpp_cap.F90" ccpp_files="${ccpp_files},${build_dir}/ccpp/ccpp_var_compatibility_suite_cap.F90" #process_list="" -module_list="effr_calc,effr_diag,effr_post,effr_pre" -#dependencies="" +module_list="effr_calc,effr_diag,effr_post,effr_pre,rad_lw,rad_sw" +dependencies="module_rad_ddt" suite_list="var_compatibility_suite" required_vars_var_compatibility="ccpp_error_code,ccpp_error_message" required_vars_var_compatibility="${required_vars_var_compatibility},cloud_graupel_number_concentration" @@ -143,7 +143,9 @@ required_vars_var_compatibility="${required_vars_var_compatibility},flag_indicat required_vars_var_compatibility="${required_vars_var_compatibility},horizontal_dimension" required_vars_var_compatibility="${required_vars_var_compatibility},horizontal_loop_begin" required_vars_var_compatibility="${required_vars_var_compatibility},horizontal_loop_end" +required_vars_var_compatibility="${required_vars_var_compatibility},longwave_radiation_fluxes" required_vars_var_compatibility="${required_vars_var_compatibility},scalar_variable_for_testing" +required_vars_var_compatibility="${required_vars_var_compatibility},shortwave_radiation_fluxes" required_vars_var_compatibility="${required_vars_var_compatibility},vertical_layer_dimension" input_vars_var_compatibility="cloud_graupel_number_concentration" #input_vars_var_compatibility="${input_vars_var_compatibility},cloud_ice_number_concentration" @@ -156,7 +158,9 @@ input_vars_var_compatibility="${input_vars_var_compatibility},flag_indicating_cl input_vars_var_compatibility="${input_vars_var_compatibility},horizontal_dimension" input_vars_var_compatibility="${input_vars_var_compatibility},horizontal_loop_begin" input_vars_var_compatibility="${input_vars_var_compatibility},horizontal_loop_end" +input_vars_var_compatibility="${input_vars_var_compatibility},longwave_radiation_fluxes" input_vars_var_compatibility="${input_vars_var_compatibility},scalar_variable_for_testing" +input_vars_var_compatibility="${input_vars_var_compatibility},shortwave_radiation_fluxes" input_vars_var_compatibility="${input_vars_var_compatibility},vertical_layer_dimension" output_vars_var_compatibility="ccpp_error_code,ccpp_error_message" output_vars_var_compatibility="${output_vars_var_compatibility},cloud_ice_number_concentration" @@ -164,7 +168,9 @@ output_vars_var_compatibility="${output_vars_var_compatibility},effective_radius output_vars_var_compatibility="${output_vars_var_compatibility},effective_radius_of_stratiform_cloud_liquid_water_particle" output_vars_var_compatibility="${output_vars_var_compatibility},effective_radius_of_stratiform_cloud_rain_particle" output_vars_var_compatibility="${output_vars_var_compatibility},effective_radius_of_stratiform_cloud_snow_particle" +output_vars_var_compatibility="${output_vars_var_compatibility},longwave_radiation_fluxes" output_vars_var_compatibility="${output_vars_var_compatibility},scalar_variable_for_testing" +output_vars_var_compatibility="${output_vars_var_compatibility},shortwave_radiation_fluxes" ## ## Run a database report and check the return string @@ -230,8 +236,8 @@ echo -e "\nChecking lists from command line" #check_datatable ${report_prog} ${datafile} "--process-list" ${process_list} check_datatable ${report_prog} ${datafile} "--module-list" ${module_list} #check_datatable ${report_prog} ${datafile} "--dependencies" ${dependencies} -check_datatable ${report_prog} ${datafile} "--suite-list" ${suite_list} \ - --sep ";" +#check_datatable ${report_prog} ${datafile} "--suite-list" ${suite_list} \ +# --sep ";" echo -e "\nChecking variables for var_compatibility suite from command line" check_datatable ${report_prog} ${datafile} "--required-variables" \ ${required_vars_var_compatibility} "var_compatibility_suite" diff --git a/test/var_compatibility_test/test_host.F90 b/test/var_compatibility_test/test_host.F90 index 3bb50da4..48e6c86b 100644 --- a/test/var_compatibility_test/test_host.F90 +++ b/test/var_compatibility_test/test_host.F90 @@ -351,7 +351,7 @@ program test character(len=cs), target :: test_parts1(1) = (/ 'radiation ' /) - character(len=cm), target :: test_invars1(8) = (/ & + character(len=cm), target :: test_invars1(10) = (/ & 'effective_radius_of_stratiform_cloud_rain_particle ', & 'effective_radius_of_stratiform_cloud_liquid_water_particle', & 'effective_radius_of_stratiform_cloud_snow_particle ', & @@ -359,9 +359,11 @@ program test 'cloud_graupel_number_concentration ', & 'scalar_variable_for_testing ', & 'flag_indicating_cloud_microphysics_has_graupel ', & - 'flag_indicating_cloud_microphysics_has_ice '/) + 'flag_indicating_cloud_microphysics_has_ice ', & + 'shortwave_radiation_fluxes ', & + 'longwave_radiation_fluxes '/) - character(len=cm), target :: test_outvars1(8) = (/ & + character(len=cm), target :: test_outvars1(10) = (/ & 'ccpp_error_code ', & 'ccpp_error_message ', & 'effective_radius_of_stratiform_cloud_ice_particle ', & @@ -369,9 +371,11 @@ program test 'effective_radius_of_stratiform_cloud_rain_particle ', & 'effective_radius_of_stratiform_cloud_snow_particle ', & 'cloud_ice_number_concentration ', & - 'scalar_variable_for_testing ' /) + 'scalar_variable_for_testing ', & + 'shortwave_radiation_fluxes ', & + 'longwave_radiation_fluxes '/) - character(len=cm), target :: test_reqvars1(12) = (/ & + character(len=cm), target :: test_reqvars1(14) = (/ & 'ccpp_error_code ', & 'ccpp_error_message ', & 'effective_radius_of_stratiform_cloud_rain_particle ', & @@ -383,7 +387,9 @@ program test 'cloud_ice_number_concentration ', & 'scalar_variable_for_testing ', & 'flag_indicating_cloud_microphysics_has_graupel ', & - 'flag_indicating_cloud_microphysics_has_ice '/) + 'flag_indicating_cloud_microphysics_has_ice ', & + 'shortwave_radiation_fluxes ', & + 'longwave_radiation_fluxes '/) type(suite_info) :: test_suites(1) logical :: run_okay diff --git a/test/var_compatibility_test/test_host_data.F90 b/test/var_compatibility_test/test_host_data.F90 index 9d0ca306..9f9b2395 100644 --- a/test/var_compatibility_test/test_host_data.F90 +++ b/test/var_compatibility_test/test_host_data.F90 @@ -1,7 +1,7 @@ module test_host_data use ccpp_kinds, only: kind_phys - + use module_rad_ddt, only: ty_rad_lw, ty_rad_sw !> \section arg_table_physics_state Argument Table !! \htmlinclude arg_table_physics_state.html type physics_state @@ -13,6 +13,10 @@ module test_host_data ncg, & ! number concentration of cloud graupel nci ! number concentration of cloud ice real(kind_phys) :: scalar_var + type(ty_rad_lw), dimension(:), allocatable :: & + fluxLW ! Longwave radiation fluxes + type(ty_rad_sw), dimension(:), allocatable :: & + fluxSW ! Shortwave radiation fluxes end type physics_state public allocate_physics_state @@ -62,6 +66,16 @@ subroutine allocate_physics_state(cols, levels, state, has_graupel, has_ice) allocate(state%nci(cols, levels)) endif + if (allocated(state%fluxLW)) then + deallocate(state%fluxLW) + end if + allocate(state%fluxLW(cols)) + + if (allocated(state%fluxSW)) then + deallocate(state%fluxSW) + end if + allocate(state%fluxSW(cols)) + end subroutine allocate_physics_state end module test_host_data diff --git a/test/var_compatibility_test/test_host_data.meta b/test/var_compatibility_test/test_host_data.meta index d3bca89b..e14c9811 100644 --- a/test/var_compatibility_test/test_host_data.meta +++ b/test/var_compatibility_test/test_host_data.meta @@ -1,6 +1,7 @@ [ccpp-table-properties] name = physics_state type = ddt + dependencies = module_rad_ddt.F90 [ccpp-arg-table] name = physics_state type = ddt @@ -59,3 +60,23 @@ dimensions = () type = real kind = kind_phys +[fluxSW] + standard_name = shortwave_radiation_fluxes + long_name = shortwave radiation fluxes + units = W m-2 + dimensions = (horizontal_dimension) + type = ty_rad_sw +[fluxLW] + standard_name = longwave_radiation_fluxes + long_name = longwave radiation fluxes + units = W m-2 + dimensions = (horizontal_dimension) + type = ty_rad_lw + +[ccpp-table-properties] + name = test_host_data + type = module + dependencies = module_rad_ddt.F90 +[ccpp-arg-table] + name = test_host_data + type = module \ No newline at end of file diff --git a/test/var_compatibility_test/test_reports.py b/test/var_compatibility_test/test_reports.py index 6f10fc6d..91b0cefe 100755 --- a/test/var_compatibility_test/test_reports.py +++ b/test/var_compatibility_test/test_reports.py @@ -65,8 +65,9 @@ def usage(errmsg=None): _CCPP_FILES = _UTILITY_FILES + \ [os.path.join(_BUILD_DIR, "ccpp", "test_host_ccpp_cap.F90"), os.path.join(_BUILD_DIR, "ccpp", "ccpp_var_compatibility_suite_cap.F90")] -_MODULE_LIST = ["effr_calc", "effr_diag", "effr_post", "effr_pre"] +_MODULE_LIST = ["effr_calc", "effr_diag", "effr_post", "effr_pre", "rad_lw", "rad_sw"] _SUITE_LIST = ["var_compatibility_suite"] +_DEPENDENCIES = [ os.path.join(_TEST_DIR, "module_rad_ddt.F90")] _INPUT_VARS_VAR_ACTION = ["horizontal_loop_begin", "horizontal_loop_end", "horizontal_dimension", "vertical_layer_dimension", "effective_radius_of_stratiform_cloud_liquid_water_particle", "effective_radius_of_stratiform_cloud_rain_particle", @@ -75,14 +76,18 @@ def usage(errmsg=None): "cloud_graupel_number_concentration", "scalar_variable_for_testing", "flag_indicating_cloud_microphysics_has_graupel", - "flag_indicating_cloud_microphysics_has_ice"] + "flag_indicating_cloud_microphysics_has_ice", + "shortwave_radiation_fluxes", + "longwave_radiation_fluxes"] _OUTPUT_VARS_VAR_ACTION = ["ccpp_error_code", "ccpp_error_message", "effective_radius_of_stratiform_cloud_ice_particle", "effective_radius_of_stratiform_cloud_liquid_water_particle", "effective_radius_of_stratiform_cloud_snow_particle", "cloud_ice_number_concentration", "effective_radius_of_stratiform_cloud_rain_particle", - "scalar_variable_for_testing"] + "scalar_variable_for_testing", + "shortwave_radiation_fluxes", + "longwave_radiation_fluxes"] _REQUIRED_VARS_VAR_ACTION = _INPUT_VARS_VAR_ACTION + _OUTPUT_VARS_VAR_ACTION def fields_string(field_type, field_list, sep): @@ -148,6 +153,8 @@ def check_datatable(database, report_type, check_list, _MODULE_LIST) NUM_ERRORS += check_datatable(_DATABASE, DatatableReport("suite_list"), _SUITE_LIST) +NUM_ERRORS += check_datatable(_DATABASE, DatatableReport("dependencies"), + _DEPENDENCIES) print("\nChecking variables for var_compatibility suite from python") NUM_ERRORS += check_datatable(_DATABASE, DatatableReport("required_variables", value="var_compatibility_suite"), diff --git a/test/var_compatibility_test/var_compatibility_files.txt b/test/var_compatibility_test/var_compatibility_files.txt index 6d83c980..71df1054 100644 --- a/test/var_compatibility_test/var_compatibility_files.txt +++ b/test/var_compatibility_test/var_compatibility_files.txt @@ -1,4 +1,7 @@ +module_rad_ddt.meta effr_calc.meta effr_diag.meta effr_pre.meta effr_post.meta +rad_lw.meta +rad_sw.meta diff --git a/test/var_compatibility_test/var_compatibility_suite.xml b/test/var_compatibility_test/var_compatibility_suite.xml index 5956a8bd..de6ebfe5 100644 --- a/test/var_compatibility_test/var_compatibility_suite.xml +++ b/test/var_compatibility_test/var_compatibility_suite.xml @@ -4,7 +4,9 @@ effr_pre effr_calc - effr_post + effr_post effr_diag + rad_lw + rad_sw From 03429da17d210c9843806f40ecb75f4a9974f210 Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Mon, 3 Feb 2025 18:32:25 +0000 Subject: [PATCH 02/15] Allow for module/source filename differences. Add test --- scripts/metadata_table.py | 52 ++++++++++++++++++- .../var_compatibility_test/module_rad_ddt.F90 | 4 +- test/var_compatibility_test/rad_lw.F90 | 2 +- test/var_compatibility_test/rad_sw.F90 | 2 +- .../var_compatibility_test/test_host_data.F90 | 2 +- 5 files changed, 55 insertions(+), 7 deletions(-) diff --git a/scripts/metadata_table.py b/scripts/metadata_table.py index 942f8d81..fc001fd8 100755 --- a/scripts/metadata_table.py +++ b/scripts/metadata_table.py @@ -223,6 +223,51 @@ def parse_metadata_file(filename, known_ddts, run_env, skip_ddt_check=False): ######################################################################## +def find_module_name(filename): + """Find the module name from module header in """ + module_name = '' + if os.path.isfile(filename): + with open(filename, 'r') as infile: + fin_lines = infile.readlines() + # end with + num_lines = len(fin_lines) + context = ParseContext(linenum=1, filename=filename) + while context.line_num <= num_lines: + if MetadataTable.table_start(fin_lines[context.line_num - 1]): + found_start = False + while not found_start: + line = fin_lines[context.line_num].strip() + context.line_num += 1 + if line and (line[0] == '['): + found_start = True + elif line: + props = _parse_config_line(line, context) + for prop in props: + # Look for name property + key = prop[0].strip().lower() + value = prop[1].strip() + if key == 'name' : + name = value + if key == 'type' : + if (value == 'module') or (value == 'scheme'): + module_name = name + break + # end if + # end for + # end if + if context.line_num > num_lines: + break + # end if + # end while + else: + context.line_num += 1 + # end if + # end while + # end if + return module_name + +######################################################################## + def find_scheme_names(filename): """Find and return a list of all the physics scheme names in . A scheme is identified by its ccpp-table-properties name. @@ -813,8 +858,11 @@ def __init_from_file(self, table_name, table_type, known_ddts, run_env, skip_ddt if self.header_type == "ddt": known_ddts.append(self.title) # end if - # We need a default module if none was listed - if self.module is None: + # We need a default module if none was listed. + # DJS2024: First, try to find module_name from the metadata. Otherwise, + # use file name as module_name (default). + self.__module_name = find_module_name(self.__pobj.filename) + if (self.__module_name == ''): self.__module_name = self._default_module() # end if # Initialize our ParseSource parent diff --git a/test/var_compatibility_test/module_rad_ddt.F90 b/test/var_compatibility_test/module_rad_ddt.F90 index 79ec12a5..fd59da43 100644 --- a/test/var_compatibility_test/module_rad_ddt.F90 +++ b/test/var_compatibility_test/module_rad_ddt.F90 @@ -4,8 +4,8 @@ module mod_rad_ddt public ty_rad_lw, ty_rad_sw - !> \section arg_table_module_rad_ddt Argument Table - !! \htmlinclude arg_table_module_rad_ddt.html + !> \section arg_table_mod_rad_ddt Argument Table + !! \htmlinclude arg_table_mod_rad_ddt.html !! !> \section arg_table_ty_rad_lw Argument Table diff --git a/test/var_compatibility_test/rad_lw.F90 b/test/var_compatibility_test/rad_lw.F90 index 6fd97ec8..5859f8bf 100644 --- a/test/var_compatibility_test/rad_lw.F90 +++ b/test/var_compatibility_test/rad_lw.F90 @@ -1,6 +1,6 @@ module rad_lw use ccpp_kinds, only: kind_phys - use module_rad_ddt, only: ty_rad_lw + use mod_rad_ddt, only: ty_rad_lw implicit none private diff --git a/test/var_compatibility_test/rad_sw.F90 b/test/var_compatibility_test/rad_sw.F90 index 4354193d..a0f22af9 100644 --- a/test/var_compatibility_test/rad_sw.F90 +++ b/test/var_compatibility_test/rad_sw.F90 @@ -1,6 +1,6 @@ module rad_sw use ccpp_kinds, only: kind_phys - use module_rad_ddt, only: ty_rad_sw + use mod_rad_ddt, only: ty_rad_sw implicit none private diff --git a/test/var_compatibility_test/test_host_data.F90 b/test/var_compatibility_test/test_host_data.F90 index 9f9b2395..b204c92c 100644 --- a/test/var_compatibility_test/test_host_data.F90 +++ b/test/var_compatibility_test/test_host_data.F90 @@ -1,7 +1,7 @@ module test_host_data use ccpp_kinds, only: kind_phys - use module_rad_ddt, only: ty_rad_lw, ty_rad_sw + use mod_rad_ddt, only: ty_rad_lw, ty_rad_sw !> \section arg_table_physics_state Argument Table !! \htmlinclude arg_table_physics_state.html type physics_state From 690215ff2abca1133e2b1806e053e6658e930a0e Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Mon, 3 Feb 2025 20:49:25 +0000 Subject: [PATCH 03/15] Add logic to allow for module name to come from initialization. Doc tests passing --- scripts/metadata_table.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/metadata_table.py b/scripts/metadata_table.py index fc001fd8..6b7c0a79 100755 --- a/scripts/metadata_table.py +++ b/scripts/metadata_table.py @@ -859,11 +859,13 @@ def __init_from_file(self, table_name, table_type, known_ddts, run_env, skip_ddt known_ddts.append(self.title) # end if # We need a default module if none was listed. - # DJS2024: First, try to find module_name from the metadata. Otherwise, - # use file name as module_name (default). - self.__module_name = find_module_name(self.__pobj.filename) - if (self.__module_name == ''): - self.__module_name = self._default_module() + # DJS2024: If module_name not provided through initialization, try + # to find module_name from the metadata. Otherwise, use file name + # as module_name (default). + if (self.__module_name == None): + self.__module_name = find_module_name(self.__pobj.filename) + if (self.__module_name == ''): + self.__module_name = self._default_module() # end if # Initialize our ParseSource parent super().__init__(self.title, self.header_type, self.__pobj) From 8fef76a37d36e09e606fa6f4a7488cb6885ea6a0 Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Mon, 3 Feb 2025 23:47:24 +0000 Subject: [PATCH 04/15] Use DDT subfields as scheme dummy arguments. Add testing --- scripts/ddt_library.py | 11 ++++++++--- test/var_compatibility_test/module_rad_ddt.F90 | 4 ++-- .../var_compatibility_test/module_rad_ddt.meta | 4 ++-- test/var_compatibility_test/rad_sw.F90 | 10 +++++----- test/var_compatibility_test/rad_sw.meta | 18 ++++++++++++------ test/var_compatibility_test/run_test | 9 ++++++--- test/var_compatibility_test/test_host.F90 | 15 +++++++++------ test/var_compatibility_test/test_host_data.F90 | 13 +++++++++---- .../var_compatibility_test/test_host_data.meta | 2 +- test/var_compatibility_test/test_reports.py | 6 ++++-- 10 files changed, 58 insertions(+), 34 deletions(-) diff --git a/scripts/ddt_library.py b/scripts/ddt_library.py index 35425599..1c362108 100644 --- a/scripts/ddt_library.py +++ b/scripts/ddt_library.py @@ -252,9 +252,10 @@ def check_ddt_type(self, var, header, lname=None): # end if (no else needed) def collect_ddt_fields(self, var_dict, var, run_env, - ddt=None, skip_duplicates=False): + ddt=None, skip_duplicates=False, parent=None): """Add all the reachable fields from DDT variable of type, to . Each field is added as a VarDDT. + If , add VarDDT recursively using parent. Note: By default, it is an error to try to add a duplicate field to (i.e., the field already exists in or one of its parents). To simply skip duplicate @@ -272,12 +273,16 @@ def collect_ddt_fields(self, var_dict, var, run_env, # end if # end if for dvar in ddt.variable_list(): - subvar = VarDDT(dvar, var, self.run_env) + if parent is None: + subvar = VarDDT(dvar, var, self.run_env) + else: + subvar = VarDDT(VarDDT(dvar, var, self.run_env), parent, self.run_env) + # end if dvtype = dvar.get_prop_value('type') if (dvar.is_ddt()) and (dvtype in self): # If DDT in our library, we need to add sub-fields recursively. subddt = self[dvtype] - self.collect_ddt_fields(var_dict, subvar, run_env, ddt=subddt) + self.collect_ddt_fields(var_dict, dvar, run_env, parent=var, ddt=subddt) # end if # add_variable only checks the current dictionary. By default, # for a DDT, the variable also cannot be in our parent diff --git a/test/var_compatibility_test/module_rad_ddt.F90 b/test/var_compatibility_test/module_rad_ddt.F90 index fd59da43..2e8af9a9 100644 --- a/test/var_compatibility_test/module_rad_ddt.F90 +++ b/test/var_compatibility_test/module_rad_ddt.F90 @@ -20,8 +20,8 @@ module mod_rad_ddt !! \htmlinclude arg_table_ty_rad_sw.html !! type ty_rad_sw - real(kind_phys) :: sfc_up_sw - real(kind_phys) :: sfc_down_sw + real(kind_phys), pointer :: sfc_up_sw(:) => null() + real(kind_phys), pointer :: sfc_down_sw(:) => null() end type ty_rad_sw end module mod_rad_ddt diff --git a/test/var_compatibility_test/module_rad_ddt.meta b/test/var_compatibility_test/module_rad_ddt.meta index f47c70e4..ee9a0a24 100644 --- a/test/var_compatibility_test/module_rad_ddt.meta +++ b/test/var_compatibility_test/module_rad_ddt.meta @@ -34,12 +34,12 @@ [ sfc_up_sw ] standard_name = surface_upwelling_shortwave_radiation_flux units = W m2 - dimensions = () + dimensions = (horizontal_dimension) type = real kind = kind_phys [ sfc_down_sw ] standard_name = surface_downwelling_shortwave_radiation_flux units = W m2 - dimensions = () + dimensions = (horizontal_dimension) type = real kind = kind_phys \ No newline at end of file diff --git a/test/var_compatibility_test/rad_sw.F90 b/test/var_compatibility_test/rad_sw.F90 index a0f22af9..ddf35224 100644 --- a/test/var_compatibility_test/rad_sw.F90 +++ b/test/var_compatibility_test/rad_sw.F90 @@ -1,6 +1,5 @@ module rad_sw use ccpp_kinds, only: kind_phys - use mod_rad_ddt, only: ty_rad_sw implicit none private @@ -12,10 +11,11 @@ module rad_sw !> \section arg_table_rad_sw_run Argument Table !! \htmlinclude arg_table_rad_sw_run.html !! - subroutine rad_sw_run(ncol, fluxSW, errmsg, errflg) + subroutine rad_sw_run(ncol, sfc_up_sw, sfc_down_sw, errmsg, errflg) integer, intent(in) :: ncol - type(ty_rad_sw), intent(inout) :: fluxSW(:) + real(kind_phys), intent(inout) :: sfc_up_sw(:) + real(kind_phys), intent(inout) :: sfc_down_sw(:) character(len=512), intent(out) :: errmsg integer, intent(out) :: errflg @@ -26,8 +26,8 @@ subroutine rad_sw_run(ncol, fluxSW, errmsg, errflg) errflg = 0 do icol=1,ncol - fluxSW(icol)%sfc_up_sw = 100._kind_phys - fluxSW(icol)%sfc_down_sw = 400._kind_phys + sfc_up_sw(icol) = 100._kind_phys + sfc_down_sw(icol) = 400._kind_phys enddo end subroutine rad_sw_run diff --git a/test/var_compatibility_test/rad_sw.meta b/test/var_compatibility_test/rad_sw.meta index 81f2d583..d88b9acc 100644 --- a/test/var_compatibility_test/rad_sw.meta +++ b/test/var_compatibility_test/rad_sw.meta @@ -1,7 +1,6 @@ [ccpp-table-properties] name = rad_sw type = scheme - dependencies = module_rad_ddt.F90 [ccpp-arg-table] name = rad_sw_run type = scheme @@ -11,12 +10,19 @@ units = count dimensions = () intent = in -[fluxSW] - standard_name = shortwave_radiation_fluxes - long_name = shortwave radiation fluxes - units = W m-2 +[ sfc_up_sw ] + standard_name = surface_upwelling_shortwave_radiation_flux + units = W m2 dimensions = (horizontal_loop_extent) - type = ty_rad_sw + type = real + kind = kind_phys + intent = inout +[ sfc_down_sw ] + standard_name = surface_downwelling_shortwave_radiation_flux + units = W m2 + dimensions = (horizontal_loop_extent) + type = real + kind = kind_phys intent = inout [ errmsg ] standard_name = ccpp_error_message diff --git a/test/var_compatibility_test/run_test b/test/var_compatibility_test/run_test index b939ab0b..3b0f55dc 100755 --- a/test/var_compatibility_test/run_test +++ b/test/var_compatibility_test/run_test @@ -146,7 +146,8 @@ required_vars_var_compatibility="${required_vars_var_compatibility},horizontal_l required_vars_var_compatibility="${required_vars_var_compatibility},longwave_radiation_fluxes" required_vars_var_compatibility="${required_vars_var_compatibility},scalar_variable_for_testing" required_vars_var_compatibility="${required_vars_var_compatibility},scheme_order_in_suite" -required_vars_var_compatibility="${required_vars_var_compatibility},shortwave_radiation_fluxes" +required_vars_var_compatibility="${required_vars_var_compatibility},surface_downwelling_shortwave_radiation_flux" +required_vars_var_compatibility="${required_vars_var_compatibility},surface_upwelling_shortwave_radiation_flux" required_vars_var_compatibility="${required_vars_var_compatibility},vertical_layer_dimension" input_vars_var_compatibility="cloud_graupel_number_concentration" #input_vars_var_compatibility="${input_vars_var_compatibility},cloud_ice_number_concentration" @@ -162,7 +163,8 @@ input_vars_var_compatibility="${input_vars_var_compatibility},horizontal_loop_en input_vars_var_compatibility="${input_vars_var_compatibility},longwave_radiation_fluxes" input_vars_var_compatibility="${input_vars_var_compatibility},scalar_variable_for_testing" input_vars_var_compatibility="${input_vars_var_compatibility},scheme_order_in_suite" -input_vars_var_compatibility="${input_vars_var_compatibility},shortwave_radiation_fluxes" +input_vars_var_compatibility="${input_vars_var_compatibility},surface_downwelling_shortwave_radiation_flux" +input_vars_var_compatibility="${input_vars_var_compatibility},surface_upwelling_shortwave_radiation_flux" input_vars_var_compatibility="${input_vars_var_compatibility},vertical_layer_dimension" output_vars_var_compatibility="ccpp_error_code,ccpp_error_message" output_vars_var_compatibility="${output_vars_var_compatibility},cloud_ice_number_concentration" @@ -173,7 +175,8 @@ output_vars_var_compatibility="${output_vars_var_compatibility},effective_radius output_vars_var_compatibility="${output_vars_var_compatibility},longwave_radiation_fluxes" output_vars_var_compatibility="${output_vars_var_compatibility},scalar_variable_for_testing" output_vars_var_compatibility="${output_vars_var_compatibility},scheme_order_in_suite" -output_vars_var_compatibility="${output_vars_var_compatibility},shortwave_radiation_fluxes" +output_vars_var_compatibility="${output_vars_var_compatibility},surface_downwelling_shortwave_radiation_flux" +output_vars_var_compatibility="${output_vars_var_compatibility},surface_upwelling_shortwave_radiation_flux" ## ## Run a database report and check the return string diff --git a/test/var_compatibility_test/test_host.F90 b/test/var_compatibility_test/test_host.F90 index b66b39df..15c20a52 100644 --- a/test/var_compatibility_test/test_host.F90 +++ b/test/var_compatibility_test/test_host.F90 @@ -351,7 +351,7 @@ program test character(len=cs), target :: test_parts1(1) = (/ 'radiation ' /) - character(len=cm), target :: test_invars1(11) = (/ & + character(len=cm), target :: test_invars1(12) = (/ & 'effective_radius_of_stratiform_cloud_rain_particle ', & 'effective_radius_of_stratiform_cloud_liquid_water_particle', & 'effective_radius_of_stratiform_cloud_snow_particle ', & @@ -361,10 +361,11 @@ program test 'scheme_order_in_suite ', & 'flag_indicating_cloud_microphysics_has_graupel ', & 'flag_indicating_cloud_microphysics_has_ice ', & - 'shortwave_radiation_fluxes ', & + 'surface_downwelling_shortwave_radiation_flux ', & + 'surface_upwelling_shortwave_radiation_flux ', & 'longwave_radiation_fluxes '/) - character(len=cm), target :: test_outvars1(11) = (/ & + character(len=cm), target :: test_outvars1(12) = (/ & 'ccpp_error_code ', & 'ccpp_error_message ', & 'effective_radius_of_stratiform_cloud_ice_particle ', & @@ -374,10 +375,11 @@ program test 'cloud_ice_number_concentration ', & 'scalar_variable_for_testing ', & 'scheme_order_in_suite ', & - 'shortwave_radiation_fluxes ', & + 'surface_downwelling_shortwave_radiation_flux ', & + 'surface_upwelling_shortwave_radiation_flux ', & 'longwave_radiation_fluxes '/) - character(len=cm), target :: test_reqvars1(15) = (/ & + character(len=cm), target :: test_reqvars1(16) = (/ & 'ccpp_error_code ', & 'ccpp_error_message ', & 'effective_radius_of_stratiform_cloud_rain_particle ', & @@ -391,7 +393,8 @@ program test 'scheme_order_in_suite ', & 'flag_indicating_cloud_microphysics_has_graupel ', & 'flag_indicating_cloud_microphysics_has_ice ', & - 'shortwave_radiation_fluxes ', & + 'surface_downwelling_shortwave_radiation_flux ', & + 'surface_upwelling_shortwave_radiation_flux ', & 'longwave_radiation_fluxes '/) type(suite_info) :: test_suites(1) diff --git a/test/var_compatibility_test/test_host_data.F90 b/test/var_compatibility_test/test_host_data.F90 index 26f72467..41772e58 100644 --- a/test/var_compatibility_test/test_host_data.F90 +++ b/test/var_compatibility_test/test_host_data.F90 @@ -15,7 +15,7 @@ module test_host_data real(kind_phys) :: scalar_var type(ty_rad_lw), dimension(:), allocatable :: & fluxLW ! Longwave radiation fluxes - type(ty_rad_sw), dimension(:), allocatable :: & + type(ty_rad_sw) :: & fluxSW ! Shortwave radiation fluxes integer :: scheme_order end type physics_state @@ -73,10 +73,15 @@ subroutine allocate_physics_state(cols, levels, state, has_graupel, has_ice) end if allocate(state%fluxLW(cols)) - if (allocated(state%fluxSW)) then - deallocate(state%fluxSW) + if (associated(state%fluxSW%sfc_up_sw)) then + nullify(state%fluxSW%sfc_up_sw) end if - allocate(state%fluxSW(cols)) + allocate(state%fluxSW%sfc_up_sw(cols)) + + if (associated(state%fluxSW%sfc_down_sw)) then + nullify(state%fluxSW%sfc_down_sw) + end if + allocate(state%fluxSW%sfc_down_sw(cols)) ! Initialize scheme counter. state%scheme_order = 1 diff --git a/test/var_compatibility_test/test_host_data.meta b/test/var_compatibility_test/test_host_data.meta index 8fb76e0e..1c8172b4 100644 --- a/test/var_compatibility_test/test_host_data.meta +++ b/test/var_compatibility_test/test_host_data.meta @@ -64,7 +64,7 @@ standard_name = shortwave_radiation_fluxes long_name = shortwave radiation fluxes units = W m-2 - dimensions = (horizontal_dimension) + dimensions = () type = ty_rad_sw [fluxLW] standard_name = longwave_radiation_fluxes diff --git a/test/var_compatibility_test/test_reports.py b/test/var_compatibility_test/test_reports.py index 9a260af5..c7555df0 100755 --- a/test/var_compatibility_test/test_reports.py +++ b/test/var_compatibility_test/test_reports.py @@ -78,7 +78,8 @@ def usage(errmsg=None): "scheme_order_in_suite", "flag_indicating_cloud_microphysics_has_graupel", "flag_indicating_cloud_microphysics_has_ice", - "shortwave_radiation_fluxes", + "surface_downwelling_shortwave_radiation_flux", + "surface_upwelling_shortwave_radiation_flux", "longwave_radiation_fluxes"] _OUTPUT_VARS_VAR_ACTION = ["ccpp_error_code", "ccpp_error_message", "effective_radius_of_stratiform_cloud_ice_particle", @@ -87,7 +88,8 @@ def usage(errmsg=None): "cloud_ice_number_concentration", "effective_radius_of_stratiform_cloud_rain_particle", "scalar_variable_for_testing", - "shortwave_radiation_fluxes", + "surface_downwelling_shortwave_radiation_flux", + "surface_upwelling_shortwave_radiation_flux", "longwave_radiation_fluxes", "scheme_order_in_suite"] _REQUIRED_VARS_VAR_ACTION = _INPUT_VARS_VAR_ACTION + _OUTPUT_VARS_VAR_ACTION From 656fdfe4d5eed9182d20c796664b98f9af2c5ffe Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Fri, 28 Feb 2025 21:04:44 +0100 Subject: [PATCH 05/15] New implementation of differing module name --- scripts/ccpp_suite.py | 9 +++- scripts/metadata_table.py | 49 +++++++------------ scripts/parse_tools/parse_source.py | 4 ++ scripts/suite_objects.py | 7 ++- test/var_compatibility_test/CMakeLists.txt | 2 +- .../var_compatibility_test/module_rad_ddt.F90 | 23 +++++++++ .../module_rad_ddt.meta | 40 +++++++++++++++ test/var_compatibility_test/rad_lw.F90 | 35 +++++++++++++ test/var_compatibility_test/rad_lw.meta | 35 +++++++++++++ test/var_compatibility_test/rad_sw.F90 | 35 +++++++++++++ test/var_compatibility_test/rad_sw.meta | 35 +++++++++++++ test/var_compatibility_test/run_test | 16 ++++-- test/var_compatibility_test/test_host.F90 | 19 ++++--- .../test_host_data.meta | 21 ++++++++ test/var_compatibility_test/test_reports.py | 9 +++- .../var_compatibility_files.txt | 3 ++ .../var_compatibility_suite.xml | 2 + 17 files changed, 292 insertions(+), 52 deletions(-) create mode 100644 test/var_compatibility_test/module_rad_ddt.F90 create mode 100644 test/var_compatibility_test/module_rad_ddt.meta create mode 100644 test/var_compatibility_test/rad_lw.F90 create mode 100644 test/var_compatibility_test/rad_lw.meta create mode 100644 test/var_compatibility_test/rad_sw.F90 create mode 100644 test/var_compatibility_test/rad_sw.meta diff --git a/scripts/ccpp_suite.py b/scripts/ccpp_suite.py index a5cc8d9d..1182fd43 100644 --- a/scripts/ccpp_suite.py +++ b/scripts/ccpp_suite.py @@ -658,8 +658,13 @@ def __init__(self, sdfs, host_model, scheme_headers, run_env): run_env, ddts=all_ddts) for header in [d for d in scheme_headers if d.header_type != 'ddt']: if header.header_type != 'scheme': - errmsg = "{} is an unknown CCPP API metadata header type, {}" - raise CCPPError(errmsg.format(header.title, header.header_type)) + if header.header_type == 'module': + errmsg = f"{header.title} is a module metadata header type." + errmsg+=" This is not an allowed CCPP scheme header type." + else: + errmsg = f"{header.title} is an unknown CCPP API metadata header type, {header.header_type}" + # end if + raise CCPPError(errmsg) # end if func_id, _, match_trans = \ CCPP_STATE_MACH.function_match(header.title) diff --git a/scripts/metadata_table.py b/scripts/metadata_table.py index 942f8d81..584e51f9 100755 --- a/scripts/metadata_table.py +++ b/scripts/metadata_table.py @@ -63,6 +63,7 @@ type = scheme relative_path = dependencies = + module = # only needed if module name differs from filename dynamic_constituent_routine = [ccpp-arg-table] @@ -285,6 +286,7 @@ def __init__(self, run_env, table_name_in=None, table_type_in=None, """ self.__pobj = parse_object self.__dependencies = dependencies + self.__module_name = module self.__relative_path = relative_path self.__sections = [] self.__run_env = run_env @@ -364,6 +366,7 @@ def __init_from_file(self, known_ddts, run_env, skip_ddt_check=False): in_properties_header = True skip_rest_of_section = False self.__dependencies = [] # Default is no dependencies + self.__module_name = self.__pobj.default_module_name() # Process lines until the end of the file or start of the next table. while ((curr_line is not None) and (not MetadataTable.table_start(curr_line))): @@ -405,6 +408,8 @@ def __init_from_file(self, known_ddts, run_env, skip_ddt_check=False): if x.strip()] self.__dependencies.extend(depends) # end if + elif key == 'module_name': + self.__module_name = value elif key == 'relative_path': self.__relative_path = value else: @@ -419,6 +424,7 @@ def __init_from_file(self, known_ddts, run_env, skip_ddt_check=False): skip_rest_of_section = False section = MetadataSection(self.table_name, self.table_type, run_env, parse_object=self.__pobj, + module=self.__module_name, known_ddts=known_ddts, skip_ddt_check=skip_ddt_check) # Some table types only allow for one associated section @@ -483,6 +489,11 @@ def dependencies(self): """Return the dependencies for this table""" return self.__dependencies + @property + def module_name(self): + """Return the module name for this metadata table""" + return self.__module + @property def relative_path(self): """Return the relative path for the table's dependencies""" @@ -652,7 +663,7 @@ def __init__(self, table_name, table_type, run_env, parse_object=None, self.__variables = None # In case __init__ crashes self.__section_title = None self.__header_type = None - self.__module_name = None + self.__module_name = module self.__process_type = UNKNOWN_PROCESS_TYPE self.__section_valid = True self.__run_env = run_env @@ -706,8 +717,8 @@ def __init__(self, table_name, table_type, run_env, parse_object=None, known_ddts = [] # end if self.__start_context = ParseContext(context=self.__pobj) - self.__init_from_file(table_name, table_type, known_ddts, run_env, - skip_ddt_check=skip_ddt_check) + self.__init_from_file(table_name, table_type, known_ddts, self.module, + run_env, skip_ddt_check=skip_ddt_check) # end if # Register this header if it is a DDT if self.header_type == 'ddt': @@ -722,27 +733,13 @@ def __init__(self, table_name, table_type, run_env, parse_object=None, # end if # end for - def _default_module(self): - """Set a default module for this header""" - mfile = self.__pobj.filename - if mfile[-5:] == '.meta': - # Default value is a Fortran module that matches the filename - def_mod = os.path.basename(mfile)[:-5] - else: - def_mod = os.path.basename(mfile) - last_dot = def_mod.rfind('.') - if last_dot >= 0: - ldef = len(def_mod) - def_mod = def_mod[:last_dot-ldef] - # end if - # end if - return def_mod - - def __init_from_file(self, table_name, table_type, known_ddts, run_env, skip_ddt_check=False): + def __init_from_file(self, table_name, table_type, known_ddts, module_name, + run_env, skip_ddt_check=False): """ Read the section preamble, assume the caller already figured out the first line of the header using the header_start method.""" start_ctx = context_string(self.__pobj) curr_line, _ = self.__pobj.next_line() # Skip past [ccpp-arg-table] + self.__module_name = module_name while ((curr_line is not None) and (not MetadataSection.variable_start(curr_line, self.__pobj)) and (not MetadataSection.header_start(curr_line)) and @@ -765,14 +762,6 @@ def __init_from_file(self, table_name, table_type, known_ddts, run_env, skip_ddt # end if # Set value even if error so future error msgs make sense self.__header_type = value - elif key == 'module': - if value != "None": - self.__module_name = value - else: - self.__pobj.add_syntax_err("metadata table, no module") - self.__module_name = 'INVALID' # Allow error continue - self.__section_valid = False - # end if elif key == 'process': self.__process_type = value else: @@ -813,10 +802,6 @@ def __init_from_file(self, table_name, table_type, known_ddts, run_env, skip_ddt if self.header_type == "ddt": known_ddts.append(self.title) # end if - # We need a default module if none was listed - if self.module is None: - self.__module_name = self._default_module() - # end if # Initialize our ParseSource parent super().__init__(self.title, self.header_type, self.__pobj) # Read the variables diff --git a/scripts/parse_tools/parse_source.py b/scripts/parse_tools/parse_source.py index 2ed0e5b8..1a4082cb 100644 --- a/scripts/parse_tools/parse_source.py +++ b/scripts/parse_tools/parse_source.py @@ -244,6 +244,10 @@ def __init__(self, linenum=None, filename=None, context=None): self.__linenum = linenum self.__filename = filename + def default_module_name(self): + """Return a default module for this file""" + return os.path.splitext(os.path.basename(self.filename))[0] + @property def line_num(self): """Return the current line""" diff --git a/scripts/suite_objects.py b/scripts/suite_objects.py index 13d2c6a2..5ac21138 100755 --- a/scripts/suite_objects.py +++ b/scripts/suite_objects.py @@ -2482,12 +2482,11 @@ def write(self, outfile, host_arglist, indent, const_mod, # end for # Look for any DDT types call_vars = self.call_list.variable_list() - self._ddt_library.write_ddt_use_statements(call_vars, outfile, - indent+1, pad=modmax) - decl_vars = ([x[0] for x in subpart_allocate_vars.values()] + + all_vars = ([x[0] for x in subpart_allocate_vars.values()] + [x[0] for x in subpart_scalar_vars.values()] + [x[0] for x in subpart_optional_vars.values()]) - self._ddt_library.write_ddt_use_statements(decl_vars, outfile, + all_vars.extend(call_vars) + self._ddt_library.write_ddt_use_statements(all_vars, outfile, indent+1, pad=modmax) outfile.write('', 0) # Write out dummy arguments diff --git a/test/var_compatibility_test/CMakeLists.txt b/test/var_compatibility_test/CMakeLists.txt index 8cbd7e44..e25f3fda 100644 --- a/test/var_compatibility_test/CMakeLists.txt +++ b/test/var_compatibility_test/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(CCPP_ROOT "${TEST_ROOT}" DIRECTORY) # #------------------------------------------------------------------------------ LIST(APPEND SCHEME_FILES "var_compatibility_files.txt") -LIST(APPEND HOST_FILES "test_host_data" "test_host_mod") +LIST(APPEND HOST_FILES "module_rad_ddt" "test_host_data" "test_host_mod") LIST(APPEND SUITE_FILES "var_compatibility_suite.xml") # HOST is the name of the executable we will build. # We assume there are files ${HOST}.meta and ${HOST}.F90 in CMAKE_SOURCE_DIR diff --git a/test/var_compatibility_test/module_rad_ddt.F90 b/test/var_compatibility_test/module_rad_ddt.F90 new file mode 100644 index 00000000..c7986a6c --- /dev/null +++ b/test/var_compatibility_test/module_rad_ddt.F90 @@ -0,0 +1,23 @@ +module mod_rad_ddt + USE ccpp_kinds, ONLY: kind_phys + implicit none + + public ty_rad_lw, ty_rad_sw + + !> \section arg_table_ty_rad_lw Argument Table + !! \htmlinclude arg_table_ty_rad_lw.html + !! + type ty_rad_lw + real(kind_phys) :: sfc_up_lw + real(kind_phys) :: sfc_down_lw + end type ty_rad_lw + + !> \section arg_table_ty_rad_sw Argument Table + !! \htmlinclude arg_table_ty_rad_sw.html + !! + type ty_rad_sw + real(kind_phys) :: sfc_up_sw + real(kind_phys) :: sfc_down_sw + end type ty_rad_sw + +end module mod_rad_ddt diff --git a/test/var_compatibility_test/module_rad_ddt.meta b/test/var_compatibility_test/module_rad_ddt.meta new file mode 100644 index 00000000..4576c151 --- /dev/null +++ b/test/var_compatibility_test/module_rad_ddt.meta @@ -0,0 +1,40 @@ +[ccpp-table-properties] + name = ty_rad_lw + type = ddt + dependencies = + module_name = mod_rad_ddt +[ccpp-arg-table] + name = ty_rad_lw + type = ddt +[ sfc_up_lw ] + standard_name = surface_upwelling_longwave_radiation_flux + units = W m2 + dimensions = () + type = real + kind = kind_phys +[ sfc_down_lw ] + standard_name = surface_downwelling_longwave_radiation_flux + units = W m2 + dimensions = () + type = real + kind = kind_phys + +[ccpp-table-properties] + name = ty_rad_sw + type = ddt + module_name = mod_rad_ddt +[ccpp-arg-table] + name = ty_rad_sw + type = ddt +[ sfc_up_sw ] + standard_name = surface_upwelling_shortwave_radiation_flux + units = W m2 + dimensions = () + type = real + kind = kind_phys +[ sfc_down_sw ] + standard_name = surface_downwelling_shortwave_radiation_flux + units = W m2 + dimensions = () + type = real + kind = kind_phys diff --git a/test/var_compatibility_test/rad_lw.F90 b/test/var_compatibility_test/rad_lw.F90 new file mode 100644 index 00000000..5859f8bf --- /dev/null +++ b/test/var_compatibility_test/rad_lw.F90 @@ -0,0 +1,35 @@ +module rad_lw + use ccpp_kinds, only: kind_phys + use mod_rad_ddt, only: ty_rad_lw + + implicit none + private + + public :: rad_lw_run + +contains + + !> \section arg_table_rad_lw_run Argument Table + !! \htmlinclude arg_table_rad_lw_run.html + !! + subroutine rad_lw_run(ncol, fluxLW, errmsg, errflg) + + integer, intent(in) :: ncol + type(ty_rad_lw), intent(inout) :: fluxLW(:) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + ! Locals + integer :: icol + + errmsg = '' + errflg = 0 + + do icol=1,ncol + fluxLW(icol)%sfc_up_lw = 300._kind_phys + fluxLW(icol)%sfc_down_lw = 50._kind_phys + enddo + + end subroutine rad_lw_run + +end module rad_lw diff --git a/test/var_compatibility_test/rad_lw.meta b/test/var_compatibility_test/rad_lw.meta new file mode 100644 index 00000000..883edf1b --- /dev/null +++ b/test/var_compatibility_test/rad_lw.meta @@ -0,0 +1,35 @@ +[ccpp-table-properties] + name = rad_lw + type = scheme + dependencies = module_rad_ddt.F90 +[ccpp-arg-table] + name = rad_lw_run + type = scheme +[ ncol ] + standard_name = horizontal_loop_extent + type = integer + units = count + dimensions = () + intent = in +[fluxLW] + standard_name = longwave_radiation_fluxes + long_name = longwave radiation fluxes + units = W m-2 + dimensions = (horizontal_loop_extent) + type = ty_rad_lw + intent = inout +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + dimensions = () + type = character + kind = len=512 + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + dimensions = () + type = integer + intent = out diff --git a/test/var_compatibility_test/rad_sw.F90 b/test/var_compatibility_test/rad_sw.F90 new file mode 100644 index 00000000..a0f22af9 --- /dev/null +++ b/test/var_compatibility_test/rad_sw.F90 @@ -0,0 +1,35 @@ +module rad_sw + use ccpp_kinds, only: kind_phys + use mod_rad_ddt, only: ty_rad_sw + + implicit none + private + + public :: rad_sw_run + +contains + + !> \section arg_table_rad_sw_run Argument Table + !! \htmlinclude arg_table_rad_sw_run.html + !! + subroutine rad_sw_run(ncol, fluxSW, errmsg, errflg) + + integer, intent(in) :: ncol + type(ty_rad_sw), intent(inout) :: fluxSW(:) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + ! Locals + integer :: icol + + errmsg = '' + errflg = 0 + + do icol=1,ncol + fluxSW(icol)%sfc_up_sw = 100._kind_phys + fluxSW(icol)%sfc_down_sw = 400._kind_phys + enddo + + end subroutine rad_sw_run + +end module rad_sw diff --git a/test/var_compatibility_test/rad_sw.meta b/test/var_compatibility_test/rad_sw.meta new file mode 100644 index 00000000..81f2d583 --- /dev/null +++ b/test/var_compatibility_test/rad_sw.meta @@ -0,0 +1,35 @@ +[ccpp-table-properties] + name = rad_sw + type = scheme + dependencies = module_rad_ddt.F90 +[ccpp-arg-table] + name = rad_sw_run + type = scheme +[ ncol ] + standard_name = horizontal_loop_extent + type = integer + units = count + dimensions = () + intent = in +[fluxSW] + standard_name = shortwave_radiation_fluxes + long_name = shortwave radiation fluxes + units = W m-2 + dimensions = (horizontal_loop_extent) + type = ty_rad_sw + intent = inout +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + dimensions = () + type = character + kind = len=512 + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + dimensions = () + type = integer + intent = out diff --git a/test/var_compatibility_test/run_test b/test/var_compatibility_test/run_test index b604def7..0da920a7 100755 --- a/test/var_compatibility_test/run_test +++ b/test/var_compatibility_test/run_test @@ -6,7 +6,7 @@ scriptdir="$( cd $( dirname $0 ); pwd -P )" ## ## Option default values ## -defdir="ct_build" +defdir="vc_build" build_dir="${currdir}/${defdir}" cleanup="PASS" # Other supported options are ALWAYS and NEVER verbosity=0 @@ -128,8 +128,8 @@ ccpp_files="${utility_files}" ccpp_files="${ccpp_files},${build_dir}/ccpp/test_host_ccpp_cap.F90" ccpp_files="${ccpp_files},${build_dir}/ccpp/ccpp_var_compatibility_suite_cap.F90" #process_list="" -module_list="effr_calc,effr_diag,effr_post,effr_pre" -#dependencies="" +module_list="effr_calc,effr_diag,effr_post,effr_pre,rad_lw,rad_sw" +dependencies="module_rad_ddt" suite_list="var_compatibility_suite" required_vars_var_compatibility="ccpp_error_code,ccpp_error_message" required_vars_var_compatibility="${required_vars_var_compatibility},cloud_graupel_number_concentration" @@ -144,12 +144,14 @@ required_vars_var_compatibility="${required_vars_var_compatibility},flag_indicat required_vars_var_compatibility="${required_vars_var_compatibility},horizontal_dimension" required_vars_var_compatibility="${required_vars_var_compatibility},horizontal_loop_begin" required_vars_var_compatibility="${required_vars_var_compatibility},horizontal_loop_end" +required_vars_var_compatibility="${required_vars_var_compatibility},longwave_radiation_fluxes" required_vars_var_compatibility="${required_vars_var_compatibility},num_subcycles_for_effr" required_vars_var_compatibility="${required_vars_var_compatibility},scalar_variable_for_testing" required_vars_var_compatibility="${required_vars_var_compatibility},scalar_variable_for_testing_a" required_vars_var_compatibility="${required_vars_var_compatibility},scalar_variable_for_testing_b" required_vars_var_compatibility="${required_vars_var_compatibility},scalar_variable_for_testing_c" required_vars_var_compatibility="${required_vars_var_compatibility},scheme_order_in_suite" +required_vars_var_compatibility="${required_vars_var_compatibility},shortwave_radiation_fluxes" required_vars_var_compatibility="${required_vars_var_compatibility},vertical_layer_dimension" input_vars_var_compatibility="cloud_graupel_number_concentration" #input_vars_var_compatibility="${input_vars_var_compatibility},cloud_ice_number_concentration" @@ -162,12 +164,14 @@ input_vars_var_compatibility="${input_vars_var_compatibility},flag_indicating_cl input_vars_var_compatibility="${input_vars_var_compatibility},horizontal_dimension" input_vars_var_compatibility="${input_vars_var_compatibility},horizontal_loop_begin" input_vars_var_compatibility="${input_vars_var_compatibility},horizontal_loop_end" +input_vars_var_compatibility="${input_vars_var_compatibility},longwave_radiation_fluxes" input_vars_var_compatibility="${input_vars_var_compatibility},num_subcycles_for_effr" input_vars_var_compatibility="${input_vars_var_compatibility},scalar_variable_for_testing" input_vars_var_compatibility="${input_vars_var_compatibility},scalar_variable_for_testing_a" input_vars_var_compatibility="${input_vars_var_compatibility},scalar_variable_for_testing_b" input_vars_var_compatibility="${input_vars_var_compatibility},scalar_variable_for_testing_c" input_vars_var_compatibility="${input_vars_var_compatibility},scheme_order_in_suite" +input_vars_var_compatibility="${input_vars_var_compatibility},shortwave_radiation_fluxes" input_vars_var_compatibility="${input_vars_var_compatibility},vertical_layer_dimension" output_vars_var_compatibility="ccpp_error_code,ccpp_error_message" output_vars_var_compatibility="${output_vars_var_compatibility},cloud_ice_number_concentration" @@ -175,8 +179,10 @@ output_vars_var_compatibility="${output_vars_var_compatibility},effective_radius output_vars_var_compatibility="${output_vars_var_compatibility},effective_radius_of_stratiform_cloud_liquid_water_particle" output_vars_var_compatibility="${output_vars_var_compatibility},effective_radius_of_stratiform_cloud_rain_particle" output_vars_var_compatibility="${output_vars_var_compatibility},effective_radius_of_stratiform_cloud_snow_particle" +output_vars_var_compatibility="${output_vars_var_compatibility},longwave_radiation_fluxes" output_vars_var_compatibility="${output_vars_var_compatibility},scalar_variable_for_testing" output_vars_var_compatibility="${output_vars_var_compatibility},scheme_order_in_suite" +output_vars_var_compatibility="${output_vars_var_compatibility},shortwave_radiation_fluxes" ## ## Run a database report and check the return string @@ -242,8 +248,8 @@ echo -e "\nChecking lists from command line" #check_datatable ${report_prog} ${datafile} "--process-list" ${process_list} check_datatable ${report_prog} ${datafile} "--module-list" ${module_list} #check_datatable ${report_prog} ${datafile} "--dependencies" ${dependencies} -check_datatable ${report_prog} ${datafile} "--suite-list" ${suite_list} \ - --sep ";" +#check_datatable ${report_prog} ${datafile} "--suite-list" ${suite_list} \ +# --sep ";" echo -e "\nChecking variables for var_compatibility suite from command line" check_datatable ${report_prog} ${datafile} "--required-variables" \ ${required_vars_var_compatibility} "var_compatibility_suite" diff --git a/test/var_compatibility_test/test_host.F90 b/test/var_compatibility_test/test_host.F90 index 5d7f2a4f..2ff05eb7 100644 --- a/test/var_compatibility_test/test_host.F90 +++ b/test/var_compatibility_test/test_host.F90 @@ -351,7 +351,7 @@ program test character(len=cs), target :: test_parts1(1) = (/ 'radiation ' /) - character(len=cm), target :: test_invars1(13) = (/ & + character(len=cm), target :: test_invars1(15) = (/ & 'effective_radius_of_stratiform_cloud_rain_particle ', & 'effective_radius_of_stratiform_cloud_liquid_water_particle', & 'effective_radius_of_stratiform_cloud_snow_particle ', & @@ -364,9 +364,11 @@ program test 'scheme_order_in_suite ', & 'num_subcycles_for_effr ', & 'flag_indicating_cloud_microphysics_has_graupel ', & - 'flag_indicating_cloud_microphysics_has_ice '/) + 'flag_indicating_cloud_microphysics_has_ice ', & + 'shortwave_radiation_fluxes ', & + 'longwave_radiation_fluxes '/) - character(len=cm), target :: test_outvars1(9) = (/ & + character(len=cm), target :: test_outvars1(11) = (/ & 'ccpp_error_code ', & 'ccpp_error_message ', & 'effective_radius_of_stratiform_cloud_ice_particle ', & @@ -375,10 +377,11 @@ program test 'effective_radius_of_stratiform_cloud_snow_particle ', & 'cloud_ice_number_concentration ', & 'scalar_variable_for_testing ', & - 'scheme_order_in_suite '/) - + 'scheme_order_in_suite ', & + 'shortwave_radiation_fluxes ', & + 'longwave_radiation_fluxes '/) - character(len=cm), target :: test_reqvars1(17) = (/ & + character(len=cm), target :: test_reqvars1(19) = (/ & 'ccpp_error_code ', & 'ccpp_error_message ', & 'effective_radius_of_stratiform_cloud_rain_particle ', & @@ -395,7 +398,9 @@ program test 'scheme_order_in_suite ', & 'num_subcycles_for_effr ', & 'flag_indicating_cloud_microphysics_has_graupel ', & - 'flag_indicating_cloud_microphysics_has_ice '/) + 'flag_indicating_cloud_microphysics_has_ice ', & + 'shortwave_radiation_fluxes ', & + 'longwave_radiation_fluxes '/) type(suite_info) :: test_suites(1) logical :: run_okay diff --git a/test/var_compatibility_test/test_host_data.meta b/test/var_compatibility_test/test_host_data.meta index 094f26d5..b507f11e 100644 --- a/test/var_compatibility_test/test_host_data.meta +++ b/test/var_compatibility_test/test_host_data.meta @@ -1,6 +1,7 @@ [ccpp-table-properties] name = physics_state type = ddt + dependencies = module_rad_ddt.F90 [ccpp-arg-table] name = physics_state type = ddt @@ -59,6 +60,18 @@ dimensions = () type = real kind = kind_phys +[fluxSW] + standard_name = shortwave_radiation_fluxes + long_name = shortwave radiation fluxes + units = W m-2 + dimensions = (horizontal_dimension) + type = ty_rad_sw +[fluxLW] + standard_name = longwave_radiation_fluxes + long_name = longwave radiation fluxes + units = W m-2 + dimensions = (horizontal_dimension) + type = ty_rad_lw [scalar_varA] standard_name = scalar_variable_for_testing_a long_name = unused scalar variable A @@ -91,3 +104,11 @@ units = None dimensions = () type = integer + +[ccpp-table-properties] + name = test_host_data + type = module + dependencies = module_rad_ddt.F90 +[ccpp-arg-table] + name = test_host_data + type = module diff --git a/test/var_compatibility_test/test_reports.py b/test/var_compatibility_test/test_reports.py index 7519d456..ad0cb60e 100755 --- a/test/var_compatibility_test/test_reports.py +++ b/test/var_compatibility_test/test_reports.py @@ -66,8 +66,9 @@ def usage(errmsg=None): _CCPP_FILES = _UTILITY_FILES + \ [os.path.join(_BUILD_DIR, "ccpp", "test_host_ccpp_cap.F90"), os.path.join(_BUILD_DIR, "ccpp", "ccpp_var_compatibility_suite_cap.F90")] -_MODULE_LIST = ["effr_calc", "effr_diag", "effr_post", "effr_pre"] +_MODULE_LIST = ["effr_calc", "effr_diag", "effr_post", "effr_pre", "rad_lw", "rad_sw"] _SUITE_LIST = ["var_compatibility_suite"] +_DEPENDENCIES = [ os.path.join(_TEST_DIR, "module_rad_ddt.F90")] _INPUT_VARS_VAR_ACTION = ["horizontal_loop_begin", "horizontal_loop_end", "horizontal_dimension", "vertical_layer_dimension", "effective_radius_of_stratiform_cloud_liquid_water_particle", "effective_radius_of_stratiform_cloud_rain_particle", @@ -81,6 +82,8 @@ def usage(errmsg=None): "scheme_order_in_suite", "flag_indicating_cloud_microphysics_has_graupel", "flag_indicating_cloud_microphysics_has_ice", + "shortwave_radiation_fluxes", + "longwave_radiation_fluxes", "num_subcycles_for_effr"] _OUTPUT_VARS_VAR_ACTION = ["ccpp_error_code", "ccpp_error_message", "effective_radius_of_stratiform_cloud_ice_particle", @@ -89,6 +92,8 @@ def usage(errmsg=None): "cloud_ice_number_concentration", "effective_radius_of_stratiform_cloud_rain_particle", "scalar_variable_for_testing", + "shortwave_radiation_fluxes", + "longwave_radiation_fluxes", "scheme_order_in_suite"] _REQUIRED_VARS_VAR_ACTION = _INPUT_VARS_VAR_ACTION + _OUTPUT_VARS_VAR_ACTION @@ -155,6 +160,8 @@ def check_datatable(database, report_type, check_list, _MODULE_LIST) NUM_ERRORS += check_datatable(_DATABASE, DatatableReport("suite_list"), _SUITE_LIST) +NUM_ERRORS += check_datatable(_DATABASE, DatatableReport("dependencies"), + _DEPENDENCIES) print("\nChecking variables for var_compatibility suite from python") NUM_ERRORS += check_datatable(_DATABASE, DatatableReport("required_variables", value="var_compatibility_suite"), diff --git a/test/var_compatibility_test/var_compatibility_files.txt b/test/var_compatibility_test/var_compatibility_files.txt index 6d83c980..71df1054 100644 --- a/test/var_compatibility_test/var_compatibility_files.txt +++ b/test/var_compatibility_test/var_compatibility_files.txt @@ -1,4 +1,7 @@ +module_rad_ddt.meta effr_calc.meta effr_diag.meta effr_pre.meta effr_post.meta +rad_lw.meta +rad_sw.meta diff --git a/test/var_compatibility_test/var_compatibility_suite.xml b/test/var_compatibility_test/var_compatibility_suite.xml index a5d4eb48..a168e2ef 100644 --- a/test/var_compatibility_test/var_compatibility_suite.xml +++ b/test/var_compatibility_test/var_compatibility_suite.xml @@ -10,5 +10,7 @@ effr_post effr_diag + rad_lw + rad_sw From eeb16c2a2e0e5c0e48b1e2279a9de0464dc4884b Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Fri, 28 Feb 2025 21:53:30 +0100 Subject: [PATCH 06/15] Fix doctests --- scripts/metadata_table.py | 132 +++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 67 deletions(-) diff --git a/scripts/metadata_table.py b/scripts/metadata_table.py index 584e51f9..622c4ff3 100755 --- a/scripts/metadata_table.py +++ b/scripts/metadata_table.py @@ -529,87 +529,87 @@ def table_start(cls, line): class MetadataSection(ParseSource): """Class to hold all information from a metadata header >>> from framework_env import CCPPFrameworkEnv - >>> _DUMMY_RUN_ENV = CCPPFrameworkEnv(None, {'host_files':'', \ - 'scheme_files':'', \ + >>> _DUMMY_RUN_ENV = CCPPFrameworkEnv(None, {'host_files':'', \ + 'scheme_files':'', \ 'suites':''}) - >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, \ - parse_object=ParseObject("foobar.txt", \ - ["name = footable", "type = scheme", "module = foo", \ - "[ im ]", "standard_name = horizontal_loop_extent", \ - "long_name = horizontal loop extent, start at 1", \ - "units = index | type = integer", \ + >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, module="foo", \ + parse_object=ParseObject("foobar.txt", \ + ["name = footable", "type = scheme", \ + "[ im ]", "standard_name = horizontal_loop_extent", \ + "long_name = horizontal loop extent, start at 1", \ + "units = index | type = integer", \ "dimensions = () | intent = in"])) #doctest: +ELLIPSIS - >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, \ - parse_object=ParseObject("foobar.txt", \ - ["name = footable", "type = scheme", "module = foobar", \ - "[ im ]", "standard_name = horizontal_loop_extent", \ - "long_name = horizontal loop extent, start at 1", \ - "units = index | type = integer", \ + >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, module="foobar", \ + parse_object=ParseObject("foobar.txt", \ + ["name = footable", "type = scheme", \ + "[ im ]", "standard_name = horizontal_loop_extent", \ + "long_name = horizontal loop extent, start at 1", \ + "units = index | type = integer", \ "dimensions = () | intent = in"])).find_variable('horizontal_loop_extent') #doctest: +ELLIPSIS - >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, \ - parse_object=ParseObject("foobar.txt", \ - ["name = footable", "type = scheme", "module = foobar", \ - "process = microphysics", "[ im ]", \ - "standard_name = horizontal_loop_extent", \ - "long_name = horizontal loop extent, start at 1", \ - "units = index | type = integer", \ + >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, module="foobar", \ + parse_object=ParseObject("foobar.txt", \ + ["name = footable", "type = scheme", \ + "process = microphysics", "[ im ]", \ + "standard_name = horizontal_loop_extent", \ + "long_name = horizontal loop extent, start at 1", \ + "units = index | type = integer", \ "dimensions = () | intent = in"])).find_variable('horizontal_loop_extent') #doctest: +ELLIPSIS - >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, \ - parse_object=ParseObject("foobar.txt", \ - ["name = footable", "type=scheme", "module = foo", \ - "[ im ]", "standard_name = horizontal_loop_extent", \ - "long_name = horizontal loop extent, start at 1", \ - "units = index | type = integer", \ - "dimensions = () | intent = in", \ + >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, module="foo", \ + parse_object=ParseObject("foobar.txt", \ + ["name = footable", "type=scheme", \ + "[ im ]", "standard_name = horizontal_loop_extent", \ + "long_name = horizontal loop extent, start at 1", \ + "units = index | type = integer", \ + "dimensions = () | intent = in", \ " subroutine foo()"])).find_variable('horizontal_loop_extent') #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): parse_source.ParseSyntaxError: Invalid variable property syntax, 'subroutine foo()', at foobar.txt:9 - >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, \ - parse_object=ParseObject("foobar.txt", \ - ["name = footable", "type = scheme", "module=foobar", \ - "[ im ]", "standard_name = horizontal_loop_extent", \ - "long_name = horizontal loop extent, start at 1", \ - "units = index | type = integer", \ - "dimensions = () | intent = in", \ + >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, module="foobar", \ + parse_object=ParseObject("foobar.txt", \ + ["name = footable", "type = scheme", \ + "[ im ]", "standard_name = horizontal_loop_extent", \ + "long_name = horizontal loop extent, start at 1", \ + "units = index | type = integer", \ + "dimensions = () | intent = in", \ ""], line_start=0)).find_variable('horizontal_loop_extent').get_prop_value('local_name') 'im' - >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, \ - parse_object=ParseObject("foobar.txt", \ - ["name = footable", "type = scheme" \ - "[ im ]", "standard_name = horizontalloop extent", \ - "long_name = horizontal loop extent, start at 1", \ - "units = index | type = integer", \ - "dimensions = () | intent = in", \ + >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, module="foo", \ + parse_object=ParseObject("foobar.txt", \ + ["name = footable", "type = scheme" \ + "[ im ]", "standard_name = horizontalloop extent", \ + "long_name = horizontal loop extent, start at 1", \ + "units = index | type = integer", \ + "dimensions = () | intent = in", \ ""], line_start=0)).find_variable('horizontal_loop_extent') - >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, \ - parse_object=ParseObject("foobar.txt", \ - ["[ccpp-arg-table]", "name = foobar", "type = scheme" \ - "[ im ]", "standard_name = horizontal loop extent", \ - "long_name = horizontal loop extent, start at 1", \ - "units = index | type = integer", \ - "dimensions = () | intent = in", \ + >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, module="foo", \ + parse_object=ParseObject("foobar.txt", \ + ["[ccpp-arg-table]", "name = foobar", "type = scheme" \ + "[ im ]", "standard_name = horizontal loop extent", \ + "long_name = horizontal loop extent, start at 1", \ + "units = index | type = integer", \ + "dimensions = () | intent = in", \ ""], line_start=0)).find_variable('horizontal_loop_extent') - >>> MetadataSection("foobar", "scheme", _DUMMY_RUN_ENV, \ - parse_object=ParseObject("foobar.txt", \ - ["name = foobar", "module = foo" \ - "[ im ]", "standard_name = horizontal loop extent", \ - "long_name = horizontal loop extent, start at 1", \ - "units = index | type = integer", \ - "dimensions = () | intent = in", \ + >>> MetadataSection("foobar", "scheme", _DUMMY_RUN_ENV, module="foo", \ + parse_object=ParseObject("foobar.txt", \ + ["name = foobar" \ + "[ im ]", "standard_name = horizontal loop extent", \ + "long_name = horizontal loop extent, start at 1", \ + "units = index | type = integer", \ + "dimensions = () | intent = in", \ ""], line_start=0)).find_variable('horizontal_loop_extent') - >>> MetadataSection("foobar", "scheme", _DUMMY_RUN_ENV, \ - parse_object=ParseObject("foobar.txt", \ - ["name = foobar", "foo = bar" \ - "[ im ]", "standard_name = horizontal loop extent", \ - "long_name = horizontal loop extent, start at 1", \ - "units = index | type = integer", \ - "dimensions = () | intent = in", \ + >>> MetadataSection("foobar", "scheme", _DUMMY_RUN_ENV, module="foo", \ + parse_object=ParseObject("foobar.txt", \ + ["name = foobar", "foo = bar" \ + "[ im ]", "standard_name = horizontal loop extent", \ + "long_name = horizontal loop extent, start at 1", \ + "units = index | type = integer", \ + "dimensions = () | intent = in", \ ""], line_start=0)).find_variable('horizontal_loop_extent') >>> MetadataSection.header_start('[ ccpp-arg-table ]') @@ -693,9 +693,7 @@ def __init__(self, table_name, table_type, run_env, parse_object=None, if mismatch: raise CCPPError(mismatch) # end if - if module is not None: - self.__module_name = module - else: + if module is None: perr = "MetadataSection requires a module name" self.__pobj.add_syntax_err(perr) self.__section_valid = False @@ -766,7 +764,7 @@ def __init_from_file(self, table_name, table_type, known_ddts, module_name, self.__process_type = value else: self.__pobj.add_syntax_err("metadata table start property", - token=value) + token=key) self.__process_type = 'INVALID' # Allow error continue self.__section_valid = False # end if From cfe5c8d57fc8db6c61a1dbf586ed4980a6b19fe5 Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Fri, 28 Feb 2025 21:58:23 +0100 Subject: [PATCH 07/15] Fix unit test failure caused by previous error message cleanup --- test/unit_tests/test_metadata_table.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit_tests/test_metadata_table.py b/test/unit_tests/test_metadata_table.py index 94ed1e67..abf48b67 100755 --- a/test/unit_tests/test_metadata_table.py +++ b/test/unit_tests/test_metadata_table.py @@ -208,7 +208,7 @@ def test_bad_table_key(self): _ = parse_metadata_file(filename, known_ddts, self._DUMMY_RUN_ENV) #print("The exception is", context.exception) - emsg = "Invalid metadata table start property, 'something', at " + emsg = "Invalid metadata table start property, 'banana', at " self.assertTrue(emsg in str(context.exception)) def test_bad_line_split(self): From 4a97ab511b1da86531584229ffbe4a6534373a12 Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Fri, 28 Feb 2025 23:11:01 +0100 Subject: [PATCH 08/15] Add scheme file with different module name as test --- scripts/metadata_table.py | 2 +- test/var_compatibility_test/effr_pre.F90 | 6 +++--- test/var_compatibility_test/effr_pre.meta | 1 + test/var_compatibility_test/run_test | 2 +- test/var_compatibility_test/test_reports.py | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/metadata_table.py b/scripts/metadata_table.py index 622c4ff3..d33e6c64 100755 --- a/scripts/metadata_table.py +++ b/scripts/metadata_table.py @@ -414,7 +414,7 @@ def __init_from_file(self, known_ddts, run_env, skip_ddt_check=False): self.__relative_path = value else: tok_type = "metadata table start property" - self.__pobj.add_syntax_err(tok_type, token=value) + self.__pobj.add_syntax_err(tok_type, token=key) # end if # end for curr_line, _ = self.__pobj.next_line() diff --git a/test/var_compatibility_test/effr_pre.F90 b/test/var_compatibility_test/effr_pre.F90 index 51f1c373..17a3b187 100644 --- a/test/var_compatibility_test/effr_pre.F90 +++ b/test/var_compatibility_test/effr_pre.F90 @@ -1,7 +1,7 @@ !Test unit conversions for intent in, inout, out variables ! -module effr_pre +module mod_effr_pre use ccpp_kinds, only: kind_phys @@ -56,5 +56,5 @@ subroutine effr_pre_run( effrr_inout, scalar_var, errmsg, errflg) endif end subroutine effr_pre_run - - end module effr_pre + +end module mod_effr_pre diff --git a/test/var_compatibility_test/effr_pre.meta b/test/var_compatibility_test/effr_pre.meta index 9c1fcf8e..251b4175 100644 --- a/test/var_compatibility_test/effr_pre.meta +++ b/test/var_compatibility_test/effr_pre.meta @@ -1,6 +1,7 @@ [ccpp-table-properties] name = effr_pre type = scheme + module_name = mod_effr_pre dependencies = ######################################################################## [ccpp-arg-table] diff --git a/test/var_compatibility_test/run_test b/test/var_compatibility_test/run_test index 0da920a7..cbaf8083 100755 --- a/test/var_compatibility_test/run_test +++ b/test/var_compatibility_test/run_test @@ -128,7 +128,7 @@ ccpp_files="${utility_files}" ccpp_files="${ccpp_files},${build_dir}/ccpp/test_host_ccpp_cap.F90" ccpp_files="${ccpp_files},${build_dir}/ccpp/ccpp_var_compatibility_suite_cap.F90" #process_list="" -module_list="effr_calc,effr_diag,effr_post,effr_pre,rad_lw,rad_sw" +module_list="effr_calc,effr_diag,effr_post,mod_effr_pre,rad_lw,rad_sw" dependencies="module_rad_ddt" suite_list="var_compatibility_suite" required_vars_var_compatibility="ccpp_error_code,ccpp_error_message" diff --git a/test/var_compatibility_test/test_reports.py b/test/var_compatibility_test/test_reports.py index ad0cb60e..4fd2863f 100755 --- a/test/var_compatibility_test/test_reports.py +++ b/test/var_compatibility_test/test_reports.py @@ -66,7 +66,7 @@ def usage(errmsg=None): _CCPP_FILES = _UTILITY_FILES + \ [os.path.join(_BUILD_DIR, "ccpp", "test_host_ccpp_cap.F90"), os.path.join(_BUILD_DIR, "ccpp", "ccpp_var_compatibility_suite_cap.F90")] -_MODULE_LIST = ["effr_calc", "effr_diag", "effr_post", "effr_pre", "rad_lw", "rad_sw"] +_MODULE_LIST = ["effr_calc", "effr_diag", "effr_post", "mod_effr_pre", "rad_lw", "rad_sw"] _SUITE_LIST = ["var_compatibility_suite"] _DEPENDENCIES = [ os.path.join(_TEST_DIR, "module_rad_ddt.F90")] _INPUT_VARS_VAR_ACTION = ["horizontal_loop_begin", "horizontal_loop_end", "horizontal_dimension", "vertical_layer_dimension", From 8349e0ce070a08026470e226af58b1143f42aad0 Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Mon, 17 Mar 2025 17:40:35 +0100 Subject: [PATCH 09/15] Allow host model DDTs to be inputs to schemes --- scripts/ccpp_capgen.py | 12 ++-- scripts/metadata_table.py | 98 ++++++++++++++++++++++++++++--- test/ddthost_test/make_ddt.F90 | 4 +- test/ddthost_test/make_ddt.meta | 5 ++ test/ddthost_test/run_test | 2 + test/ddthost_test/test_host.F90 | 10 ++-- test/ddthost_test/test_reports.py | 3 +- 7 files changed, 114 insertions(+), 20 deletions(-) diff --git a/scripts/ccpp_capgen.py b/scripts/ccpp_capgen.py index 9eac0ecf..c18fa5e8 100755 --- a/scripts/ccpp_capgen.py +++ b/scripts/ccpp_capgen.py @@ -25,7 +25,7 @@ from framework_env import parse_command_line from host_cap import write_host_cap from host_model import HostModel -from metadata_table import parse_metadata_file, SCHEME_HEADER_TYPE +from metadata_table import parse_metadata_file, register_ddts, SCHEME_HEADER_TYPE from parse_tools import init_log, set_log_level, context_string from parse_tools import register_fortran_ddt_name from parse_tools import CCPPError, ParseInternalError @@ -524,7 +524,8 @@ def parse_host_model_files(host_filenames, host_name, run_env): return host_model ############################################################################### -def parse_scheme_files(scheme_filenames, run_env, skip_ddt_check=False): +def parse_scheme_files(scheme_filenames, run_env, skip_ddt_check=False, + known_ddts=list()): ############################################################################### """ Gather information from scheme files (e.g., init, run, and finalize @@ -532,7 +533,6 @@ def parse_scheme_files(scheme_filenames, run_env, skip_ddt_check=False): """ table_dict = {} # Duplicate check and for dependencies processing header_dict = {} # To check for duplicates - known_ddts = list() logger = run_env.logger for filename in scheme_filenames: logger.info('Reading CCPP schemes from {}'.format(filename)) @@ -643,9 +643,11 @@ def capgen(run_env, return_db=False): # We always need to parse the constituent DDTs const_prop_mod = os.path.join(src_dir, "ccpp_constituent_prop_mod.meta") if const_prop_mod not in scheme_files: - scheme_files= [const_prop_mod] + scheme_files + scheme_files = [const_prop_mod] + scheme_files # end if - scheme_headers, scheme_tdict = parse_scheme_files(scheme_files, run_env) + host_ddts = register_ddts(host_files) + scheme_headers, scheme_tdict = parse_scheme_files(scheme_files, run_env, + known_ddts=host_ddts) if run_env.verbose: ddts = host_model.ddt_lib.keys() if ddts: diff --git a/scripts/metadata_table.py b/scripts/metadata_table.py index d33e6c64..ff15d1fe 100755 --- a/scripts/metadata_table.py +++ b/scripts/metadata_table.py @@ -168,7 +168,7 @@ def _parse_config_line(line, context): else: properties = line.strip().split('|') for prop in properties: - pitems = prop.split('=', 1) + pitems = [x.strip() for x in prop.split('=', 1)] if len(pitems) >= 2: parse_items.append(pitems) else: @@ -246,8 +246,8 @@ def find_scheme_names(filename): props = _parse_config_line(line, context) for prop in props: # Look for name property - key = prop[0].strip().lower() - value = prop[1].strip() + key = prop[0].lower() + value = prop[1] if key == 'name': scheme_names.append(value) # end if @@ -265,6 +265,86 @@ def find_scheme_names(filename): ######################################################################## +def register_ddts(file_list): + """Scan the metadata files in and register all + DDT tables found. + Return a list of the DDTs type names found. + """ + errors = "" + ddt_names = set() + for mfile in file_list: + if os.path.exists(mfile): + with open(mfile, 'r') as infile: + fin_lines = infile.readlines() + # end with + pobj = ParseObject(mfile, fin_lines) + in_table = False # Line number of table start + ddt_name = "" + table_is_ddt = False + # Search the file for ccpp-table-properties sections + curr_line, line_num = pobj.next_line() + while(curr_line): + if in_table: + # We are in a table properties sec, look for name and type + if MetadataSection.header_start(curr_line) or \ + MetadataTable.table_start(curr_line): + # We have exited the table, record if a DDT + if table_is_ddt: + if ddt_name: + ddt_names.add(ddt_name) + else: + emsg = "Unnamed CCPP metadata table" + pobj.add_syntax_err(emsg) + # end if + # end if + in_table = False + ddt_name = "" + table_is_ddt = False + else: + for prop in _parse_config_line(curr_line, context=pobj): + if prop[0].lower() == 'name': + ddt_name = prop[1].lower() + elif prop[0].lower() == 'type': + table_is_ddt = prop[1].lower() == 'ddt' + # end if + # end for + # end if + elif MetadataTable.table_start(curr_line): + in_table = line_num + 1 + # end if + curr_line, line_num = pobj.next_line() + # end while + if pobj.error_message: + if errors: + errors += "\n" + # end if + errors += pobj.error_message + # end if + else: + if errors: + errors += "\n" + # end if + errors += f"Metadata file, '{mfile}', not found." + # end if + # end for + if in_table: + # This is a malformed CCPP metadata file! + if errors: + errors += "\n" + # end if + errors += f"Malformed CCPP metadata file, '{mfile}'" + # end if + if errors: + raise CCPPError(f"{errors}") + else: + for ddt in ddt_names: + register_fortran_ddt_name(ddt) + # end for + # end if + return list(ddt_names) + +######################################################################## + class MetadataTable(): """Class to hold a CCPP Metadata table including the table header (ccpp-table-properties section) and all of the associated table @@ -379,8 +459,8 @@ def __init_from_file(self, known_ddts, run_env, skip_ddt_check=False): # Process the properties in this table header line for prop in _parse_config_line(curr_line, self.__pobj): # Manually parse name, type, and table properties - key = prop[0].strip().lower() - value = prop[1].strip() + key = prop[0].lower() + value = prop[1] if key == 'name': self.__table_name = value elif key == 'type': @@ -744,8 +824,8 @@ def __init_from_file(self, table_name, table_type, known_ddts, module_name, (not MetadataTable.table_start(curr_line))): for prop in _parse_config_line(curr_line, self.__pobj): # Manually parse name, type, and module properties - key = prop[0].strip().lower() - value = prop[1].strip() + key = prop[0].lower() + value = prop[1] if key == 'name': self.__section_title = value elif key == 'type': @@ -866,8 +946,8 @@ def parse_variable(self, curr_line, known_ddts, skip_ddt_check=False): if valid_line: properties = _parse_config_line(curr_line, self.__pobj) for prop in properties: - pname = prop[0].strip().lower() - pval_str = prop[1].strip() + pname = prop[0].lower() + pval_str = prop[1] if ((pname == 'type') and (not check_fortran_intrinsic(pval_str, error=False))): if skip_ddt_check or pval_str in known_ddts: diff --git a/test/ddthost_test/make_ddt.F90 b/test/ddthost_test/make_ddt.F90 index e94aaff4..c9d0832b 100644 --- a/test/ddthost_test/make_ddt.F90 +++ b/test/ddthost_test/make_ddt.F90 @@ -69,10 +69,12 @@ end subroutine make_ddt_run !> \section arg_table_make_ddt_init Argument Table !! \htmlinclude arg_table_make_ddt_init.html !! - subroutine make_ddt_init(nbox, vmr, errmsg, errflg) + subroutine make_ddt_init(nbox, ccpp_info, vmr, errmsg, errflg) + use host_ccpp_ddt, only: ccpp_info_t ! Dummy arguments integer, intent(in) :: nbox + type(ccpp_info_t), intent(in) :: ccpp_info type(vmr_type), intent(out) :: vmr character(len=512), intent(out) :: errmsg integer, intent(out) :: errflg diff --git a/test/ddthost_test/make_ddt.meta b/test/ddthost_test/make_ddt.meta index b9dbd8a9..4f5c9a00 100644 --- a/test/ddthost_test/make_ddt.meta +++ b/test/ddthost_test/make_ddt.meta @@ -76,6 +76,11 @@ units = count dimensions = () intent = in +[ ccpp_info ] + standard_name = host_standard_ccpp_type + type = ccpp_info_t + dimensions = () + intent = in [ vmr ] standard_name = volume_mixing_ratio_ddt dimensions = () diff --git a/test/ddthost_test/run_test b/test/ddthost_test/run_test index 98b934b4..964bface 100755 --- a/test/ddthost_test/run_test +++ b/test/ddthost_test/run_test @@ -136,12 +136,14 @@ suite_list="ddt_suite;temp_suite" required_vars_ddt="ccpp_error_code,ccpp_error_message,horizontal_dimension" required_vars_ddt="${required_vars_ddt},horizontal_loop_begin" required_vars_ddt="${required_vars_ddt},horizontal_loop_end" +required_vars_ddt="${required_vars_ddt},host_standard_ccpp_type" required_vars_ddt="${required_vars_ddt},model_times" required_vars_ddt="${required_vars_ddt},number_of_model_times" required_vars_ddt="${required_vars_ddt},surface_air_pressure" input_vars_ddt="horizontal_dimension" input_vars_ddt="${input_vars_ddt},horizontal_loop_begin" input_vars_ddt="${input_vars_ddt},horizontal_loop_end" +input_vars_ddt="${input_vars_ddt},host_standard_ccpp_type" input_vars_ddt="${input_vars_ddt},model_times,number_of_model_times" input_vars_ddt="${input_vars_ddt},surface_air_pressure" output_vars_ddt="ccpp_error_code,ccpp_error_message" diff --git a/test/ddthost_test/test_host.F90 b/test/ddthost_test/test_host.F90 index d060e59e..12c4aeb0 100644 --- a/test/ddthost_test/test_host.F90 +++ b/test/ddthost_test/test_host.F90 @@ -386,10 +386,11 @@ program test 'ccpp_error_code ', & 'ccpp_error_message ' /) - character(len=cm), target :: test_invars2(3) = (/ & + character(len=cm), target :: test_invars2(4) = (/ & 'model_times ', & 'number_of_model_times ', & - 'surface_air_pressure ' /) + 'surface_air_pressure ', & + 'host_standard_ccpp_type ' /) character(len=cm), target :: test_outvars2(5) = (/ & 'ccpp_error_code ', & @@ -398,12 +399,13 @@ program test 'surface_air_pressure ', & 'number_of_model_times ' /) - character(len=cm), target :: test_reqvars2(5) = (/ & + character(len=cm), target :: test_reqvars2(6) = (/ & 'model_times ', & 'number_of_model_times ', & 'surface_air_pressure ', & 'ccpp_error_code ', & - 'ccpp_error_message ' /) + 'ccpp_error_message ', & + 'host_standard_ccpp_type ' /) type(suite_info) :: test_suites(2) logical :: run_okay diff --git a/test/ddthost_test/test_reports.py b/test/ddthost_test/test_reports.py index e2904a6e..6fec8be4 100644 --- a/test/ddthost_test/test_reports.py +++ b/test/ddthost_test/test_reports.py @@ -64,7 +64,8 @@ _SUITE_LIST = ["ddt_suite", "temp_suite"] _INPUT_VARS_DDT = ["model_times", "number_of_model_times", "horizontal_loop_begin", "horizontal_loop_end", - "surface_air_pressure", "horizontal_dimension"] + "surface_air_pressure", "horizontal_dimension", + "host_standard_ccpp_type"] _OUTPUT_VARS_DDT = ["ccpp_error_code", "ccpp_error_message", "model_times", "number_of_model_times", "surface_air_pressure"] _REQUIRED_VARS_DDT = _INPUT_VARS_DDT + _OUTPUT_VARS_DDT From e260dd53ab626aaee3d26b601a6b619968e3d436 Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Sun, 13 Apr 2025 21:49:59 +0200 Subject: [PATCH 10/15] Host model uses DDT defined in schemes. --- scripts/ccpp_capgen.py | 11 +++++++---- scripts/metadata_table.py | 8 ++++++-- test/var_compatibility_test/CMakeLists.txt | 2 +- test/var_compatibility_test/test_host_data.F90 | 17 ++++++++++++++++- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/scripts/ccpp_capgen.py b/scripts/ccpp_capgen.py index c18fa5e8..31421571 100755 --- a/scripts/ccpp_capgen.py +++ b/scripts/ccpp_capgen.py @@ -468,7 +468,8 @@ def duplicate_item_error(title, filename, itype, orig_item): raise CCPPError(errmsg.format(**edict)) ############################################################################### -def parse_host_model_files(host_filenames, host_name, run_env): +def parse_host_model_files(host_filenames, host_name, run_env, + known_ddts=list()): ############################################################################### """ Gather information from host files (e.g., DDTs, registry) and @@ -476,7 +477,6 @@ def parse_host_model_files(host_filenames, host_name, run_env): """ header_dict = {} table_dict = {} - known_ddts = list() logger = run_env.logger for filename in host_filenames: logger.info('Reading host model data from {}'.format(filename)) @@ -637,8 +637,11 @@ def capgen(run_env, return_db=False): if run_env.generate_docfiles: raise CCPPError("--generate-docfiles not yet supported") # end if - # First up, handle the host files - host_model = parse_host_model_files(host_files, host_name, run_env) + # The host model may depend on suite DDTs + scheme_ddts = register_ddts(scheme_files) + # Handle the host files + host_model = parse_host_model_files(host_files, host_name, run_env, + known_ddts=scheme_ddts) # Next, parse the scheme files # We always need to parse the constituent DDTs const_prop_mod = os.path.join(src_dir, "ccpp_constituent_prop_mod.meta") diff --git a/scripts/metadata_table.py b/scripts/metadata_table.py index ff15d1fe..125b308c 100755 --- a/scripts/metadata_table.py +++ b/scripts/metadata_table.py @@ -283,7 +283,7 @@ def register_ddts(file_list): table_is_ddt = False # Search the file for ccpp-table-properties sections curr_line, line_num = pobj.next_line() - while(curr_line): + while(curr_line is not None): if in_table: # We are in a table properties sec, look for name and type if MetadataSection.header_start(curr_line) or \ @@ -297,7 +297,11 @@ def register_ddts(file_list): pobj.add_syntax_err(emsg) # end if # end if - in_table = False + if MetadataTable.table_start(curr_line): + in_table = line_num + 1 + else: + in_table = False + # end if ddt_name = "" table_is_ddt = False else: diff --git a/test/var_compatibility_test/CMakeLists.txt b/test/var_compatibility_test/CMakeLists.txt index e25f3fda..34734c06 100644 --- a/test/var_compatibility_test/CMakeLists.txt +++ b/test/var_compatibility_test/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(CCPP_ROOT "${TEST_ROOT}" DIRECTORY) # #------------------------------------------------------------------------------ LIST(APPEND SCHEME_FILES "var_compatibility_files.txt") -LIST(APPEND HOST_FILES "module_rad_ddt" "test_host_data" "test_host_mod") +LIST(APPEND HOST_FILES "test_host_data" "test_host_mod") LIST(APPEND SUITE_FILES "var_compatibility_suite.xml") # HOST is the name of the executable we will build. # We assume there are files ${HOST}.meta and ${HOST}.F90 in CMAKE_SOURCE_DIR diff --git a/test/var_compatibility_test/test_host_data.F90 b/test/var_compatibility_test/test_host_data.F90 index 2c5e3409..964c88e7 100644 --- a/test/var_compatibility_test/test_host_data.F90 +++ b/test/var_compatibility_test/test_host_data.F90 @@ -1,6 +1,7 @@ module test_host_data - use ccpp_kinds, only: kind_phys + use ccpp_kinds, only: kind_phys + use mod_rad_ddt, only: ty_rad_lw, ty_rad_sw implicit none private @@ -15,6 +16,10 @@ module test_host_data effrg, & ! effective radius of cloud graupel ncg, & ! number concentration of cloud graupel nci ! number concentration of cloud ice + type(ty_rad_lw), dimension(:), allocatable :: & + fluxLW ! Longwave radiation fluxes + type(ty_rad_sw), dimension(:), allocatable :: & + fluxSW ! Shortwave radiation fluxes real(kind_phys) :: scalar_var real(kind_phys) :: scalar_varA real(kind_phys) :: scalar_varB @@ -72,6 +77,16 @@ subroutine allocate_physics_state(cols, levels, state, has_graupel, has_ice) allocate(state%nci(cols, levels)) endif + if (allocated(state%fluxLW)) then + deallocate(state%fluxLW) + end if + allocate(state%fluxLW(cols)) + + if (allocated(state%fluxSW)) then + deallocate(state%fluxSW) + end if + allocate(state%fluxSW(cols)) + ! Initialize scheme counter. state%scheme_order = 1 ! Initialize subcycle counter. From f4e57b1b894492fedc71167aa9e1c7094fe2a3bd Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Sun, 13 Apr 2025 22:07:04 +0200 Subject: [PATCH 11/15] Uncomment and fix var_compatibility_test checks --- test/var_compatibility_test/run_test | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/var_compatibility_test/run_test b/test/var_compatibility_test/run_test index cbaf8083..be8f1f6c 100755 --- a/test/var_compatibility_test/run_test +++ b/test/var_compatibility_test/run_test @@ -1,6 +1,6 @@ #! /bin/bash -currdir="`pwd -P`" +currdir="$(pwd -P)" scriptdir="$( cd $( dirname $0 ); pwd -P )" ## @@ -129,7 +129,7 @@ ccpp_files="${ccpp_files},${build_dir}/ccpp/test_host_ccpp_cap.F90" ccpp_files="${ccpp_files},${build_dir}/ccpp/ccpp_var_compatibility_suite_cap.F90" #process_list="" module_list="effr_calc,effr_diag,effr_post,mod_effr_pre,rad_lw,rad_sw" -dependencies="module_rad_ddt" +dependencies="${scriptdir}/module_rad_ddt.F90" suite_list="var_compatibility_suite" required_vars_var_compatibility="ccpp_error_code,ccpp_error_message" required_vars_var_compatibility="${required_vars_var_compatibility},cloud_graupel_number_concentration" @@ -245,11 +245,11 @@ check_datatable ${report_prog} ${datafile} "--suite-files" ${suite_files} check_datatable ${report_prog} ${datafile} "--utility-files" ${utility_files} check_datatable ${report_prog} ${datafile} "--ccpp-files" ${ccpp_files} echo -e "\nChecking lists from command line" -#check_datatable ${report_prog} ${datafile} "--process-list" ${process_list} +check_datatable ${report_prog} ${datafile} "--process-list" ${process_list} check_datatable ${report_prog} ${datafile} "--module-list" ${module_list} -#check_datatable ${report_prog} ${datafile} "--dependencies" ${dependencies} -#check_datatable ${report_prog} ${datafile} "--suite-list" ${suite_list} \ -# --sep ";" +check_datatable ${report_prog} ${datafile} "--dependencies" ${dependencies} +check_datatable ${report_prog} ${datafile} "--suite-list" ${suite_list} \ + --sep ";" echo -e "\nChecking variables for var_compatibility suite from command line" check_datatable ${report_prog} ${datafile} "--required-variables" \ ${required_vars_var_compatibility} "var_compatibility_suite" From 6c2d326a43d1e4fc6f344b70e0b10cfb87104432 Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Mon, 21 Apr 2025 22:11:14 +0200 Subject: [PATCH 12/15] Fix typo --- scripts/metadata_table.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/metadata_table.py b/scripts/metadata_table.py index 125b308c..bd388716 100755 --- a/scripts/metadata_table.py +++ b/scripts/metadata_table.py @@ -576,7 +576,7 @@ def dependencies(self): @property def module_name(self): """Return the module name for this metadata table""" - return self.__module + return self.__module_name @property def relative_path(self): From 15b779f05c2e94b7a34784873999926d3c151e7e Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Tue, 22 Apr 2025 14:54:00 +0000 Subject: [PATCH 13/15] Revert changes in 637 --- scripts/ccpp_suite.py | 3 +- scripts/metadata_table.py | 55 +------------------ scripts/suite_objects.py | 6 +- .../var_compatibility_test/module_rad_ddt.F90 | 4 -- .../module_rad_ddt.meta | 11 +--- 5 files changed, 10 insertions(+), 69 deletions(-) diff --git a/scripts/ccpp_suite.py b/scripts/ccpp_suite.py index 212bdf55..a5cc8d9d 100644 --- a/scripts/ccpp_suite.py +++ b/scripts/ccpp_suite.py @@ -657,8 +657,7 @@ def __init__(self, sdfs, host_model, scheme_headers, run_env): self.__ddt_lib = DDTLibrary('{}_api'.format(self.host_model.name), run_env, ddts=all_ddts) for header in [d for d in scheme_headers if d.header_type != 'ddt']: - # DJS2024: Schemes and modules with DDTs? - if header.header_type != 'scheme' and header.header_type != 'module': + if header.header_type != 'scheme': errmsg = "{} is an unknown CCPP API metadata header type, {}" raise CCPPError(errmsg.format(header.title, header.header_type)) # end if diff --git a/scripts/metadata_table.py b/scripts/metadata_table.py index 6b7c0a79..19f357e6 100755 --- a/scripts/metadata_table.py +++ b/scripts/metadata_table.py @@ -223,51 +223,6 @@ def parse_metadata_file(filename, known_ddts, run_env, skip_ddt_check=False): ######################################################################## -def find_module_name(filename): - """Find the module name from module header in """ - module_name = '' - if os.path.isfile(filename): - with open(filename, 'r') as infile: - fin_lines = infile.readlines() - # end with - num_lines = len(fin_lines) - context = ParseContext(linenum=1, filename=filename) - while context.line_num <= num_lines: - if MetadataTable.table_start(fin_lines[context.line_num - 1]): - found_start = False - while not found_start: - line = fin_lines[context.line_num].strip() - context.line_num += 1 - if line and (line[0] == '['): - found_start = True - elif line: - props = _parse_config_line(line, context) - for prop in props: - # Look for name property - key = prop[0].strip().lower() - value = prop[1].strip() - if key == 'name' : - name = value - if key == 'type' : - if (value == 'module') or (value == 'scheme'): - module_name = name - break - # end if - # end for - # end if - if context.line_num > num_lines: - break - # end if - # end while - else: - context.line_num += 1 - # end if - # end while - # end if - return module_name - -######################################################################## - def find_scheme_names(filename): """Find and return a list of all the physics scheme names in . A scheme is identified by its ccpp-table-properties name. @@ -859,14 +814,10 @@ def __init_from_file(self, table_name, table_type, known_ddts, run_env, skip_ddt known_ddts.append(self.title) # end if # We need a default module if none was listed. - # DJS2024: If module_name not provided through initialization, try - # to find module_name from the metadata. Otherwise, use file name - # as module_name (default). - if (self.__module_name == None): - self.__module_name = find_module_name(self.__pobj.filename) - if (self.__module_name == ''): - self.__module_name = self._default_module() + if self.module is None: + self.__module_name = self._default_module() # end if + # Initialize our ParseSource parent super().__init__(self.title, self.header_type, self.__pobj) # Read the variables diff --git a/scripts/suite_objects.py b/scripts/suite_objects.py index 13d2c6a2..9cadb5e0 100755 --- a/scripts/suite_objects.py +++ b/scripts/suite_objects.py @@ -1795,8 +1795,8 @@ def write(self, outfile, errcode, errmsg, indent): if self.__optional_vars: outfile.write('! Associate conditional variables', indent+1) # end if - for (dict_var, var, var_ptr, has_transform) in self.__optional_vars: - tstmt = self.associate_optional_var(dict_var, var, var_ptr, has_transform, cldicts, indent+1, outfile) + for (dict_var, var, has_transform) in self.__optional_vars: + tstmt = self.associate_optional_var(dict_var, var, has_transform, cldicts, indent+1, outfile) # end for # # Write the scheme call. @@ -1812,7 +1812,7 @@ def write(self, outfile, errcode, errmsg, indent): # Copy any local pointers. # first_ptr_declaration=True - for (dict_var, var, var_ptr, has_transform) in self.__optional_vars: + for (dict_var, var, has_transform) in self.__optional_vars: if first_ptr_declaration: outfile.write('! Copy any local pointers to dummy/local variables', indent+1) first_ptr_declaration=False diff --git a/test/var_compatibility_test/module_rad_ddt.F90 b/test/var_compatibility_test/module_rad_ddt.F90 index 2e8af9a9..d793d661 100644 --- a/test/var_compatibility_test/module_rad_ddt.F90 +++ b/test/var_compatibility_test/module_rad_ddt.F90 @@ -4,10 +4,6 @@ module mod_rad_ddt public ty_rad_lw, ty_rad_sw - !> \section arg_table_mod_rad_ddt Argument Table - !! \htmlinclude arg_table_mod_rad_ddt.html - !! - !> \section arg_table_ty_rad_lw Argument Table !! \htmlinclude arg_table_ty_rad_lw.html !! diff --git a/test/var_compatibility_test/module_rad_ddt.meta b/test/var_compatibility_test/module_rad_ddt.meta index ee9a0a24..2b715c7c 100644 --- a/test/var_compatibility_test/module_rad_ddt.meta +++ b/test/var_compatibility_test/module_rad_ddt.meta @@ -1,14 +1,8 @@ -[ccpp-table-properties] - name = mod_rad_ddt - type = module -[ccpp-arg-table] - name = mod_rad_ddt - type = module - [ccpp-table-properties] name = ty_rad_lw type = ddt - dependencies = + dependencies = + module_name = mod_rad_ddt [ccpp-arg-table] name = ty_rad_lw type = ddt @@ -28,6 +22,7 @@ [ccpp-table-properties] name = ty_rad_sw type = ddt + module_name = mod_rad_ddt [ccpp-arg-table] name = ty_rad_sw type = ddt From 15dd1915d2bed7c2f812f51231b99f84421817b6 Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Tue, 22 Apr 2025 15:40:26 +0000 Subject: [PATCH 14/15] Fix some things in merge --- scripts/suite_objects.py | 6 +++--- test/var_compatibility_test/run_test | 4 ++-- test/var_compatibility_test/test_host_data.F90 | 4 ---- test/var_compatibility_test/test_reports.py | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/scripts/suite_objects.py b/scripts/suite_objects.py index abde4cee..5ac21138 100755 --- a/scripts/suite_objects.py +++ b/scripts/suite_objects.py @@ -1795,8 +1795,8 @@ def write(self, outfile, errcode, errmsg, indent): if self.__optional_vars: outfile.write('! Associate conditional variables', indent+1) # end if - for (dict_var, var, has_transform) in self.__optional_vars: - tstmt = self.associate_optional_var(dict_var, var, has_transform, cldicts, indent+1, outfile) + for (dict_var, var, var_ptr, has_transform) in self.__optional_vars: + tstmt = self.associate_optional_var(dict_var, var, var_ptr, has_transform, cldicts, indent+1, outfile) # end for # # Write the scheme call. @@ -1812,7 +1812,7 @@ def write(self, outfile, errcode, errmsg, indent): # Copy any local pointers. # first_ptr_declaration=True - for (dict_var, var, has_transform) in self.__optional_vars: + for (dict_var, var, var_ptr, has_transform) in self.__optional_vars: if first_ptr_declaration: outfile.write('! Copy any local pointers to dummy/local variables', indent+1) first_ptr_declaration=False diff --git a/test/var_compatibility_test/run_test b/test/var_compatibility_test/run_test index 0690b61d..aabe8dd3 100755 --- a/test/var_compatibility_test/run_test +++ b/test/var_compatibility_test/run_test @@ -128,8 +128,8 @@ ccpp_files="${utility_files}" ccpp_files="${ccpp_files},${build_dir}/ccpp/test_host_ccpp_cap.F90" ccpp_files="${ccpp_files},${build_dir}/ccpp/ccpp_var_compatibility_suite_cap.F90" #process_list="" -module_list="effr_calc,effr_diag,effr_post,effr_pre,rad_lw,rad_sw" -dependencies="module_rad_ddt" +module_list="effr_calc,effr_diag,effr_post,mod_effr_pre,rad_lw,rad_sw" +dependencies="${scriptdir}/module_rad_ddt.F90" suite_list="var_compatibility_suite" required_vars_var_compatibility="ccpp_error_code,ccpp_error_message" required_vars_var_compatibility="${required_vars_var_compatibility},cloud_graupel_number_concentration" diff --git a/test/var_compatibility_test/test_host_data.F90 b/test/var_compatibility_test/test_host_data.F90 index 31234e35..c1a34d33 100644 --- a/test/var_compatibility_test/test_host_data.F90 +++ b/test/var_compatibility_test/test_host_data.F90 @@ -16,10 +16,6 @@ module test_host_data effrg, & ! effective radius of cloud graupel ncg, & ! number concentration of cloud graupel nci ! number concentration of cloud ice - type(ty_rad_lw), dimension(:), allocatable :: & - fluxLW ! Longwave radiation fluxes - type(ty_rad_sw), dimension(:), allocatable :: & - fluxSW ! Shortwave radiation fluxes real(kind_phys) :: scalar_var type(ty_rad_lw), dimension(:), allocatable :: & fluxLW ! Longwave radiation fluxes diff --git a/test/var_compatibility_test/test_reports.py b/test/var_compatibility_test/test_reports.py index bef1edd9..03760ab7 100755 --- a/test/var_compatibility_test/test_reports.py +++ b/test/var_compatibility_test/test_reports.py @@ -66,7 +66,7 @@ def usage(errmsg=None): _CCPP_FILES = _UTILITY_FILES + \ [os.path.join(_BUILD_DIR, "ccpp", "test_host_ccpp_cap.F90"), os.path.join(_BUILD_DIR, "ccpp", "ccpp_var_compatibility_suite_cap.F90")] -_MODULE_LIST = ["effr_calc", "effr_diag", "effr_post", "effr_pre", "rad_lw", "rad_sw"] +_MODULE_LIST = ["effr_calc", "effr_diag", "effr_post", "mod_effr_pre", "rad_lw", "rad_sw"] _SUITE_LIST = ["var_compatibility_suite"] _DEPENDENCIES = [ os.path.join(_TEST_DIR, "module_rad_ddt.F90")] _INPUT_VARS_VAR_ACTION = ["horizontal_loop_begin", "horizontal_loop_end", "horizontal_dimension", "vertical_layer_dimension", From aad7177a9a4be0f17908d854b4cb4e63167df321 Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Thu, 22 May 2025 16:08:37 +0000 Subject: [PATCH 15/15] Add checks to compare LW/SW fluxes against expected values --- test/var_compatibility_test/test_host_mod.F90 | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/var_compatibility_test/test_host_mod.F90 b/test/var_compatibility_test/test_host_mod.F90 index 5cd4846a..efaeb368 100644 --- a/test/var_compatibility_test/test_host_mod.F90 +++ b/test/var_compatibility_test/test_host_mod.F90 @@ -54,6 +54,10 @@ logical function compare_data() real(kind_phys), parameter :: scalar_expected = 2.0E3 ! 2 km, in meter real(kind_phys), parameter :: tke_expected = 10.0 ! 10 J kg-1 real(kind_phys), parameter :: tolerance = 1.0E-6 ! used as scaling factor for expected value + real(kind_phys), parameter :: sfc_up_sw_expected = 100. ! W/m2 + real(kind_phys), parameter :: sfc_down_sw_expected = 400. ! W/m2 + real(kind_phys), parameter :: sfc_up_lw_expected = 300. ! W/m2 + real(kind_phys), parameter :: sfc_down_lw_expected = 50. ! W/m2 compare_data = .true. @@ -92,6 +96,31 @@ logical function compare_data() abs( phys_state%tke - tke_expected), ' > ', tolerance*tke_expected compare_data = .false. end if + + if (maxval(abs( phys_state%fluxSW%sfc_up_sw - sfc_up_sw_expected)) > tolerance*sfc_up_sw_expected) then + write(6, '(a,e16.7,a,e16.7)') 'Error: max diff of sfc_up_sw from expected value exceeds tolerance: ', & + abs( phys_state%fluxSW%sfc_up_sw - sfc_up_sw_expected), ' > ', tolerance*sfc_up_sw_expected + compare_data = .false. + end if + + if (maxval(abs( phys_state%fluxSW%sfc_down_sw - sfc_down_sw_expected)) > tolerance*sfc_down_sw_expected) then + write(6, '(a,e16.7,a,e16.7)') 'Error: max diff of sfc_down_sw from expected value exceeds tolerance: ', & + abs( phys_state%fluxSW%sfc_down_sw - sfc_down_sw_expected), ' > ', tolerance*sfc_down_sw_expected + compare_data = .false. + end if + + if (maxval(abs( phys_state%fluxLW%sfc_up_lw - sfc_up_lw_expected)) > tolerance*sfc_up_lw_expected) then + write(6, '(a,e16.7,a,e16.7)') 'Error: max diff of sfc_up_lw from expected value exceeds tolerance: ', & + abs( phys_state%fluxLW%sfc_up_lw - sfc_up_lw_expected), ' > ', tolerance*sfc_up_lw_expected + compare_data = .false. + end if + + if (maxval(abs( phys_state%fluxLW%sfc_down_lw - sfc_down_lw_expected)) > tolerance*sfc_down_lw_expected) then + write(6, '(a,e16.7,a,e16.7)') 'Error: max diff of sfc_down_lw from expected value exceeds tolerance: ', & + abs( phys_state%fluxLW%sfc_down_lw - sfc_down_lw_expected), ' > ', tolerance*sfc_down_lw_expected + compare_data = .false. + end if + end function compare_data end module test_host_mod