Skip to content

Commit

Permalink
Merge branch 'feature/capgen' of https://github.com/NCAR/ccpp-framework
Browse files Browse the repository at this point in the history
… into add_optional_attr
  • Loading branch information
dustinswales committed Mar 6, 2024
2 parents b0ad2df + ff28d15 commit 809fc91
Show file tree
Hide file tree
Showing 14 changed files with 120 additions and 28 deletions.
6 changes: 5 additions & 1 deletion scripts/ccpp_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from parse_tools import read_xml_file, validate_xml_file, find_schema_version
from parse_tools import init_log, set_log_to_null
from suite_objects import CallList, Group, Scheme
from metavar import CCPP_LOOP_VAR_STDNAMES

# pylint: disable=too-many-lines

Expand Down Expand Up @@ -286,13 +287,16 @@ def find_variable(self, standard_name=None, source_var=None,
loop_subst=loop_subst)
if var is None:
# No dice? Check for a group variable which can be promoted
if standard_name in self.__gvar_stdnames:
# Don't promote loop standard names
if (standard_name in self.__gvar_stdnames and standard_name
not in CCPP_LOOP_VAR_STDNAMES):
group = self.__gvar_stdnames[standard_name]
var = group.find_variable(standard_name=standard_name,
source_var=source_var,
any_scope=False,
search_call_list=srch_clist,
loop_subst=loop_subst)

if var is not None:
# Promote variable to suite level
# Remove this entry to avoid looping back here
Expand Down
2 changes: 1 addition & 1 deletion scripts/metavar.py
Original file line number Diff line number Diff line change
Expand Up @@ -1751,9 +1751,9 @@ def add_variable_dimensions(self, var, ignore_sources, to_dict=None,
err_ret += f"{self.name}: "
err_ret += f"Cannot find variable for dimension, {dimname}, of {vstdname}{ctx}"
if dvar:
err_ret += f"\nFound {lname} from excluded source, '{dvar.source.ptype}'{dctx}"
lname = dvar.get_prop_value('local_name')
dctx = context_string(dvar.context)
err_ret += f"\nFound {lname} from excluded source, '{dvar.source.ptype}'{dctx}"
# end if
# end if
# end if
Expand Down
45 changes: 33 additions & 12 deletions scripts/suite_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -1595,13 +1595,31 @@ def add_var_transform(self, var, compat_obj, vert_dim):

# If needed, modify vertical dimension for vertical orientation flipping
_, vdim = find_vertical_dimension(var.get_dimensions())
vdim_name = vert_dim.split(':')[-1]
group_vvar = self.__group.call_list.find_variable(vdim_name)
vname = group_vvar.get_prop_value('local_name')
lindices[vdim] = '1:'+vname
rindices[vdim] = '1:'+vname
if compat_obj.has_vert_transforms:
rindices[vdim] = vname+':1:-1'
if vdim >= 0:
vdims = vert_dim.split(':')
vdim_name = vdims[-1]
group_vvar = self.__group.call_list.find_variable(vdim_name)
if group_vvar is None:
raise CCPPError(f"add_var_transform: Cannot find dimension variable, {vdim_name}")
# end if
vname = group_vvar.get_prop_value('local_name')
if len(vdims) == 2:
sdim_name = vdims[0]
group_vvar = self.find_variable(sdim_name)
if group_vvar is None:
raise CCPPError(f"add_var_transform: Cannot find dimension variable, {sdim_name}")
# end if
sname = group_vvar.get_prop_value('local_name')
else:
sname = '1'
# end if
lindices[vdim] = sname+':'+vname
if compat_obj.has_vert_transforms:
rindices[vdim] = vname+':'+sname+':-1'
else:
rindices[vdim] = sname+':'+vname
# end if
# end if

# If needed, modify horizontal dimension for loop substitution.
# NOT YET IMPLEMENTED
Expand Down Expand Up @@ -1690,9 +1708,8 @@ def write(self, outfile, errcode, errmsg, indent):
# end if
#
# Write any reverse (pre-Scheme) transforms.
#
if self.__reverse_transforms:
outfile.write('! Compute reverse (pre-scheme) transforms', indent+1)
if len(self.__reverse_transforms) > 0:
outfile.comment('Compute reverse (pre-scheme) transforms', indent+1)
# end if
for (dummy, var, rindices, lindices, compat_obj) in self.__reverse_transforms:
tstmt = self.write_var_transform(var, dummy, rindices, lindices, compat_obj, outfile, indent+1, False)
Expand Down Expand Up @@ -1730,8 +1747,8 @@ def write(self, outfile, errcode, errmsg, indent):
#
# Write any forward (post-Scheme) transforms.
#
if self.__forward_transforms:
outfile.write('! Compute forward (post-scheme) transforms', indent+1)
if len(self.__forward_transforms) > 0:
outfile.comment('Compute forward (post-scheme) transforms', indent+1)
# end if
for (var, dummy, lindices, rindices, compat_obj) in self.__forward_transforms:
tstmt = self.write_var_transform(var, dummy, rindices, lindices, compat_obj, outfile, indent+1, True)
Expand Down Expand Up @@ -1832,6 +1849,10 @@ def analyze(self, phase, group, scheme_library, suite_vars, level):
local_dim = group.call_list.find_variable(standard_name=dim_name,
any_scope=False)
# end if
# If not found, check the suite level
if local_dim is None:
local_dim = group.suite.find_variable(standard_name=dim_name)
# end if
if local_dim is None:
emsg = 'No variable found for vertical loop dimension {}'
raise ParseInternalError(emsg.format(self._dim_name))
Expand Down
30 changes: 26 additions & 4 deletions scripts/var_props.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,18 @@ class VarCompatObj:
_DOCTEST_RUNENV).reverse_transform("var1_lname", "var2_lname", ('k',), ('nk-k+1',))
'var1_lname(nk-k+1) = var2_lname(k)'
# Test that unit conversions with a scalar var works
>>> VarCompatObj("var_stdname", "real", "kind_phys", "Pa", [], "var1_lname", False, \
"var_stdname", "real", "kind_phys", "hPa", [], "var2_lname", False, \
_DOCTEST_RUNENV).forward_transform("var1_lname", "var2_lname", [], []) #doctest: +ELLIPSIS
'var1_lname = 1.0E-2_kind_phys*var2_lname'
# Test that unit conversions with a scalar var works
>>> VarCompatObj("var_stdname", "real", "kind_phys", "Pa", [], "var1_lname", False, \
"var_stdname", "real", "kind_phys", "hPa", [], "var2_lname", False, \
_DOCTEST_RUNENV).reverse_transform("var1_lname", "var2_lname", [], []) #doctest: +ELLIPSIS
'var1_lname = 1.0E+2_kind_phys*var2_lname'
# Test that a 2-D var with unit conversion m->km works
>>> VarCompatObj("var_stdname", "real", "kind_phys", "m", ['horizontal_dimension'], "var1_lname", False, \
"var_stdname", "real", "kind_phys", "km", ['horizontal_dimension'], "var2_lname", False, \
Expand Down Expand Up @@ -976,8 +988,13 @@ def forward_transform(self, lvar_lname, rvar_lname, rvar_indices, lvar_indices,
"vertical_interface_dimension").
"""
# Dimension transform (Indices handled externally)
rhs_term = f"{rvar_lname}({','.join(rvar_indices)})"
lhs_term = f"{lvar_lname}({','.join(lvar_indices)})"
if len(rvar_indices) == 0:
rhs_term = f"{rvar_lname}"
lhs_term = f"{lvar_lname}"
else:
rhs_term = f"{rvar_lname}({','.join(rvar_indices)})"
lhs_term = f"{lvar_lname}({','.join(lvar_indices)})"
# end if

if self.has_kind_transforms:
kind = self.__kind_transforms[1]
Expand Down Expand Up @@ -1016,8 +1033,13 @@ def reverse_transform(self, lvar_lname, rvar_lname, rvar_indices, lvar_indices,
"vertical_interface_dimension").
"""
# Dimension transforms (Indices handled externally)
lhs_term = f"{lvar_lname}({','.join(lvar_indices)})"
rhs_term = f"{rvar_lname}({','.join(rvar_indices)})"
if len(rvar_indices) == 0:
rhs_term = f"{rvar_lname}"
lhs_term = f"{lvar_lname}"
else:
lhs_term = f"{lvar_lname}({','.join(lvar_indices)})"
rhs_term = f"{rvar_lname}({','.join(rvar_indices)})"
# end if

if self.has_kind_transforms:
kind = self.__kind_transforms[0]
Expand Down
4 changes: 3 additions & 1 deletion test/capgen_test/temp_suite.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>

<suite name="temp_suite" version="1.0">
<group name="physics">
<group name="physics1">
<scheme>temp_set</scheme>
</group>
<group name="physics2">
<scheme>temp_calc_adjust</scheme>
<scheme>temp_adjust</scheme>
</group>
Expand Down
3 changes: 2 additions & 1 deletion test/capgen_test/test_host.F90
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ program test

implicit none

character(len=cs), target :: test_parts1(1) = (/ 'physics ' /)
character(len=cs), target :: test_parts1(2) = (/ 'physics1 ', &
'physics2 ' /)
character(len=cs), target :: test_parts2(1) = (/ 'data_prep ' /)
character(len=cm), target :: test_invars1(6) = (/ &
'potential_temperature ', &
Expand Down
8 changes: 6 additions & 2 deletions test/var_compatibility_test/effr_calc.F90
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ module effr_calc
!! \htmlinclude arg_table_effr_calc_run.html
!!
subroutine effr_calc_run(ncol, nlev, effrr_in, effrg_in, ncg_in, nci_out, &
effrl_inout, effri_out, effrs_inout, ncl_out, errmsg, errflg)
effrl_inout, effri_out, effrs_inout, ncl_out, &
has_graupel, scalar_var, errmsg, errflg)

integer, intent(in) :: ncol
integer, intent(in) :: nlev
Expand All @@ -27,9 +28,11 @@ subroutine effr_calc_run(ncol, nlev, effrr_in, effrg_in, ncg_in, nci_out, &
real(kind_phys), intent(inout) :: effrl_inout(:,:)
real(kind_phys), intent(out),optional :: effri_out(:,:)
real(8),intent(inout) :: effrs_inout(:,:)
real(kind_phys), intent(out),optional :: ncl_out(:,:)
logical, intent(in) :: has_graupel
real(kind_phys), intent(inout) :: scalar_var
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errflg
real(kind_phys), intent(out),optional :: ncl_out(:,:)
!----------------------------------------------------------------

real(kind_phys), parameter :: re_qc_min = 2.5 ! microns
Expand All @@ -50,6 +53,7 @@ subroutine effr_calc_run(ncol, nlev, effrr_in, effrg_in, ncg_in, nci_out, &
effrl_inout = min(max(effrl_inout,re_qc_min),re_qc_max)
if (present(effri_out)) effri_out = re_qi_avg
effrs_inout = effrs_inout + 10.0 ! in micrometer
scalar_var = 2.0 ! in km

end subroutine effr_calc_run

Expand Down
15 changes: 15 additions & 0 deletions test/var_compatibility_test/effr_calc.meta
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,21 @@
kind = kind_phys
intent = out
optional = True
[has_graupel]
standard_name = flag_indicating_cloud_microphysics_has_graupel
long_name = flag indicating that the cloud microphysics produces graupel
units = flag
dimensions = ()
type = logical
intent = in
[ scalar_var ]
standard_name = scalar_variable_for_testing
long_name = scalar variable for testing
units = km
dimensions = ()
type = real
kind = kind_phys
intent = inout
[ errmsg ]
standard_name = ccpp_error_message
long_name = Error message for error handling in CCPP
Expand Down
3 changes: 3 additions & 0 deletions test/var_compatibility_test/run_test
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ 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},scalar_variable_for_testing"
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"
Expand All @@ -155,12 +156,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},scalar_variable_for_testing"
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"
output_vars_var_compatibility="${output_vars_var_compatibility},effective_radius_of_stratiform_cloud_ice_particle"
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_snow_particle"
output_vars_var_compatibility="${output_vars_var_compatibility},scalar_variable_for_testing"


##
Expand Down
11 changes: 7 additions & 4 deletions test/var_compatibility_test/test_host.F90
Original file line number Diff line number Diff line change
Expand Up @@ -351,24 +351,26 @@ program test

character(len=cs), target :: test_parts1(1) = (/ 'radiation ' /)

character(len=cm), target :: test_invars1(7) = (/ &
character(len=cm), target :: test_invars1(8) = (/ &
'effective_radius_of_stratiform_cloud_rain_particle ', &
'effective_radius_of_stratiform_cloud_liquid_water_particle', &
'effective_radius_of_stratiform_cloud_snow_particle ', &
'effective_radius_of_stratiform_cloud_graupel ', &
'cloud_graupel_number_concentration ', &
'scalar_variable_for_testing ', &
'flag_indicating_cloud_microphysics_has_graupel ', &
'flag_indicating_cloud_microphysics_has_ice '/)

character(len=cm), target :: test_outvars1(6) = (/ &
character(len=cm), target :: test_outvars1(7) = (/ &
'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 '/)
'cloud_ice_number_concentration ', &
'scalar_variable_for_testing ' /)

character(len=cm), target :: test_reqvars1(11) = (/ &
character(len=cm), target :: test_reqvars1(12) = (/ &
'ccpp_error_code ', &
'ccpp_error_message ', &
'effective_radius_of_stratiform_cloud_rain_particle ', &
Expand All @@ -378,6 +380,7 @@ program test
'effective_radius_of_stratiform_cloud_graupel ', &
'cloud_graupel_number_concentration ', &
'cloud_ice_number_concentration ', &
'scalar_variable_for_testing ', &
'flag_indicating_cloud_microphysics_has_graupel ', &
'flag_indicating_cloud_microphysics_has_ice '/)

Expand Down
1 change: 1 addition & 0 deletions test/var_compatibility_test/test_host_data.F90
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module test_host_data
effrg, & ! effective radius of cloud graupel
ncg, & ! number concentration of cloud graupel
nci ! number concentration of cloud ice
real(kind_phys) :: scalar_var
end type physics_state

public allocate_physics_state
Expand Down
7 changes: 7 additions & 0 deletions test/var_compatibility_test/test_host_data.meta
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,10 @@
kind = kind_phys
intent = in
active = (flag_indicating_cloud_microphysics_has_ice)
[scalar_var]
standard_name = scalar_variable_for_testing
long_name = unused scalar variable
units = m
dimensions = ()
type = real
kind = kind_phys
9 changes: 8 additions & 1 deletion test/var_compatibility_test/test_host_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ subroutine init_data()
call allocate_physics_state(ncols, pver, phys_state, has_graupel, has_ice)
phys_state%effrr = 1.0E-3 ! 1000 microns, in meter
phys_state%effrl = 1.0E-4 ! 100 microns, in meter
! phys_state%effri = 5.0E-5 ! 50 microns, in meter
phys_state%scalar_var = 1.0 ! in m
effrs = 5.0E-4 ! 500 microns, in meter
if (has_graupel) then
phys_state%effrg = 2.5E-4 ! 250 microns, in meter
Expand All @@ -46,6 +46,7 @@ logical function compare_data()
real(kind_phys), parameter :: effrl_expected = 5.0E-5 ! 50 microns, in meter
real(kind_phys), parameter :: effri_expected = 7.5E-5 ! 75 microns, in meter
real(kind_phys), parameter :: effrs_expected = 5.1E-4 ! 510 microns, in meter
real(kind_phys), parameter :: scalar_expected = 2.0E3 ! 2 km, in meter
real(kind_phys), parameter :: tolerance = 1.0E-6 ! used as scaling factor for expected value

compare_data = .true.
Expand Down Expand Up @@ -74,6 +75,12 @@ logical function compare_data()
compare_data = .false.
end if

if (abs( phys_state%scalar_var - scalar_expected) > tolerance*scalar_expected) then
write(6, '(a,e16.7,a,e16.7)') 'Error: max diff of scalar_var from expected value exceeds tolerance: ', &
abs( phys_state%scalar_var - scalar_expected), ' > ', tolerance*scalar_expected
compare_data = .false.
end if

end function compare_data

end module test_host_mod
4 changes: 3 additions & 1 deletion test/var_compatibility_test/test_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,15 @@ def usage(errmsg=None):
"effective_radius_of_stratiform_cloud_snow_particle",
"effective_radius_of_stratiform_cloud_graupel",
"cloud_graupel_number_concentration",
"scalar_variable_for_testing",
"flag_indicating_cloud_microphysics_has_graupel",
"flag_indicating_cloud_microphysics_has_ice"]
_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"]
"cloud_ice_number_concentration",
"scalar_variable_for_testing"]
_REQUIRED_VARS_VAR_ACTION = _INPUT_VARS_VAR_ACTION + _OUTPUT_VARS_VAR_ACTION

def fields_string(field_type, field_list, sep):
Expand Down

0 comments on commit 809fc91

Please sign in to comment.