Closed climbfuji closed 4 years ago
This feature was implemented in a broader context for the gsd/develop branch in https://github.com/NOAA-GSD/ccpp-framework/pull/4. The new attribute is (temporarily) called active
, since it is not only required for debug checks, but also for handling blocked data structures and performing unit conversions (skip both if the variable is not active). The syntax is the same as described above.
For example, the metadata in GFS_typedefs.meta has the following conditions for some of the tracer variables:
...
[qgrs(:,:,index_for_water_friendly_aerosols)]
standard_name = water_friendly_aerosol_number_concentration
long_name = number concentration of water-friendly aerosols
units = kg-1
dimensions = (horizontal_dimension,vertical_dimension)
active = (index_for_water_friendly_aerosols > 0)
type = real
kind = kind_phys
...
[nwfa2d]
standard_name = tendency_of_water_friendly_aerosols_at_surface
long_name = instantaneous water-friendly sfc aerosol source
units = kg-1 s-1
dimensions = (horizontal_dimension)
active = (flag_for_microphysics_scheme == flag_for_thompson_microphysics_scheme .and. flag_for_aerosol_physics)
type = real
kind = kind_phys
...
The parser understands all possible Fortran syntax used in logical expressions:
FORTRAN_CONDITIONAL_REGEX_WORDS = [' ', '(', ')', '==', '/=', '<=', '>=', '<', '>', '.eqv.', '.neqv.',
'.true.', '.false.', '.lt.', '.le.', '.eq.', '.ge.', '.gt.', '.ne.',
'.not.', '.and.', '.or.', '.xor.']
FORTRAN_CONDITIONAL_REGEX = re.compile(r"[\w']+|" + "|".join([word.replace('(','\(').replace(')', '\)') for word in FORTRAN_CONDITIONAL_REGEX_WORDS]))
This is used as follows:
# If the variable is only active/used under certain conditions, add necessary variables
# also record the conditional for later use in unit conversions / blocked data conversions.
if var.active == 'T':
conditional = '.true.'
elif var.active == 'F':
conditional = '.false.'
else:
# Convert conditional expression in standard_name format to local names known to the host model
conditional = ''
# Find all words in the conditional, for each of them look for a matching
# standard name in the list of known variables
items = FORTRAN_CONDITIONAL_REGEX.findall(var.active.lower())
for item in items:
if item in FORTRAN_CONDITIONAL_REGEX_WORDS:
conditional += item
else:
# Detect integers, following Python's "easier to ask forgiveness than permission" mentality
try:
int(item)
conditional += item
except ValueError:
if not item in metadata_define.keys():
raise Exception("Variable {} used in conditional for {} not known to host model".format(
item, var_standard_name))
var2 = metadata_define[item][0]
conditional += var2.local_name
This feature request is superseded by #325.
We need to be able to debug auto-generated code correctly.
The Intel compiler (and possibly others) do not detect out-of-bounds errors if they are inside argument lists passed to a subroutine. We therefore need to add logic that enables the compiler to check for bounds (or do the check ourselves), check if an array is allocated etc.
This is further complicated by the presence of arrays that may or may not be allocated, depending on some condition. Example: In the UFS, 3-dim. diagnostic tracer arrays are only allocated if
ldiag3d
is true.An idea here is to have a new metadata attribute that enables debug checks, which by default is true:
but can contain a logical expression in standard names, for the example of a 3-dim. diagnostic tracer array:
or, for the example of an array that is only allocated if an integer is set to a certain value:
or a combination, for example: