Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

DRAFT: Capgen in SCM: DDT subfields into Group Caps #640

Draft
wants to merge 8 commits into
base: develop
Choose a base branch
from
3 changes: 2 additions & 1 deletion scripts/ccpp_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 8 additions & 3 deletions scripts/ddt_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <var> of type,
<ddt> to <var_dict>. Each field is added as a VarDDT.
If <parent>, add VarDDT recursively using parent.
Note: By default, it is an error to try to add a duplicate
field to <var_dict> (i.e., the field already exists in
<var_dict> or one of its parents). To simply skip duplicate
Expand All @@ -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
Expand Down
56 changes: 53 additions & 3 deletions scripts/metadata_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <filename>"""
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
<filename>. A scheme is identified by its ccpp-table-properties name.
Expand Down Expand Up @@ -813,9 +858,14 @@ 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()
# 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()
# end if
# Initialize our ParseSource parent
super().__init__(self.title, self.header_type, self.__pobj)
Expand Down
2 changes: 1 addition & 1 deletion test/var_compatibility_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 28 additions & 0 deletions test/var_compatibility_test/module_rad_ddt.F90
Original file line number Diff line number Diff line change
@@ -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_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
!!
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), pointer :: sfc_up_sw(:) => null()
real(kind_phys), pointer :: sfc_down_sw(:) => null()
end type ty_rad_sw

end module mod_rad_ddt

45 changes: 45 additions & 0 deletions test/var_compatibility_test/module_rad_ddt.meta
Original file line number Diff line number Diff line change
@@ -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 = (horizontal_dimension)
type = real
kind = kind_phys
[ sfc_down_sw ]
standard_name = surface_downwelling_shortwave_radiation_flux
units = W m2
dimensions = (horizontal_dimension)
type = real
kind = kind_phys
35 changes: 35 additions & 0 deletions test/var_compatibility_test/rad_lw.F90
Original file line number Diff line number Diff line change
@@ -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
35 changes: 35 additions & 0 deletions test/var_compatibility_test/rad_lw.meta
Original file line number Diff line number Diff line change
@@ -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
35 changes: 35 additions & 0 deletions test/var_compatibility_test/rad_sw.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module rad_sw
use ccpp_kinds, only: kind_phys

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, sfc_up_sw, sfc_down_sw, errmsg, errflg)

integer, intent(in) :: ncol
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

! Locals
integer :: icol

errmsg = ''
errflg = 0

do icol=1,ncol
sfc_up_sw(icol) = 100._kind_phys
sfc_down_sw(icol) = 400._kind_phys
enddo

end subroutine rad_sw_run

end module rad_sw
41 changes: 41 additions & 0 deletions test/var_compatibility_test/rad_sw.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[ccpp-table-properties]
name = rad_sw
type = scheme
[ccpp-arg-table]
name = rad_sw_run
type = scheme
[ ncol ]
standard_name = horizontal_loop_extent
type = integer
units = count
dimensions = ()
intent = in
[ sfc_up_sw ]
standard_name = surface_upwelling_shortwave_radiation_flux
units = W m2
dimensions = (horizontal_loop_extent)
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
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
Loading