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

New "is_scheme_constituent" interface #6

Merged
merged 7 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions scripts/constituents.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,16 +456,17 @@ def write_constituent_use_statements(cap, suite_list, indent):

@staticmethod
def write_host_routines(cap, host, reg_funcname, init_funcname, num_const_funcname,
copy_in_funcname, copy_out_funcname, const_obj_name,
const_names_name, const_indices_name, const_array_func,
advect_array_func, prop_array_func,
query_const_funcname, copy_in_funcname, copy_out_funcname,
const_obj_name, const_names_name, const_indices_name,
const_array_func, advect_array_func, prop_array_func,
const_index_func, suite_list, err_vars):
"""Write out the host model <reg_funcname> routine which will
instantiate constituent fields for all the constituents in <suite_list>.
<err_vars> is a list of the host model's error variables.
Also write out the following routines:
<init_funcname>: Initialize constituent data
<num_const_funcname>: Number of constituents
<query_const_funcname>: Check if standard name matches existing constituent
<copy_in_funcname>: Collect constituent fields for host
<copy_out_funcname>: Update constituent fields from host
<const_array_func>: Return a pointer to the constituent array
Expand Down Expand Up @@ -634,6 +635,23 @@ def write_host_routines(cap, host, reg_funcname, init_funcname, num_const_funcna
call_str = "call {}%num_constituents(num_flds, advected=advected, {})"
cap.write(call_str.format(const_obj_name, obj_err_callstr), 2)
cap.write("end {}".format(substmt), 1)
# Write query_consts routine
substmt = f"subroutine {query_const_funcname}"
cap.blank_line()
cap.write(f"{substmt}(var_name, constituent_exists, {err_dummy_str})", 1)
cap.comment(f"Return constituent_exists = true iff var_name appears in {host.name}_model_const_stdnames", 2)
cap.blank_line()
cap.write("character(len=*), intent(in) :: var_name", 2)
cap.write("logical, intent(out) :: constituent_exists", 2)
for evar in err_vars:
evar.write_def(cap, 2, host, dummy=True, add_intent="out")
# end for
cap.write("constituent_exists = .false.", 2)
cap.write(f"if (any({host.name}_model_const_stdnames == var_name)) then", 2)
cap.write("constituent_exists = .true.", 3)
cap.write("end if", 2)
cap.blank_line()
cap.write(f"end {substmt}", 1)
# Write copy_in routine
substmt = "subroutine {}".format(copy_in_funcname)
cap.write("", 0)
Expand Down
25 changes: 18 additions & 7 deletions scripts/host_cap.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ def constituent_num_consts_funcname(host_model):
Because this is a user interface API function, the name is fixed."""
return "{}_ccpp_number_constituents".format(host_model.name)

###############################################################################
def query_scheme_constituents_funcname(host_model):
###############################################################################
"""Return the name of the function to return True if the standard name
passed in matches an existing constituent
Because this is a user interface API function, the name is fixed."""
return f"{host_model.name}_ccpp_is_scheme_constituent"

###############################################################################
def constituent_copyin_subname(host_model):
###############################################################################
Expand Down Expand Up @@ -444,15 +452,17 @@ def write_host_cap(host_model, api, module_name, output_dir, run_env):
API.declare_inspection_interfaces(cap)
# Write the host-model interfaces for constituents
reg_name = constituent_register_subname(host_model)
cap.write("public :: {}".format(reg_name), 1)
cap.write(f"public :: {reg_name}", 1)
init_name = constituent_initialize_subname(host_model)
cap.write("public :: {}".format(init_name), 1)
cap.write(f"public :: {init_name}", 1)
numconsts_name = constituent_num_consts_funcname(host_model)
cap.write("public :: {}".format(numconsts_name), 1)
cap.write(f"public :: {numconsts_name}", 1)
queryconsts_name = query_scheme_constituents_funcname(host_model)
cap.write(f"public :: {queryconsts_name}", 1)
copyin_name = constituent_copyin_subname(host_model)
cap.write("public :: {}".format(copyin_name), 1)
cap.write(f"public :: {copyin_name}", 1)
copyout_name = constituent_copyout_subname(host_model)
cap.write("public :: {}".format(copyout_name), 1)
cap.write(f"public :: {copyout_name}", 1)
const_array_func = constituent_model_consts(host_model)
cap.write(f"public :: {const_array_func}", 1)
advect_array_func = constituent_model_advected_consts(host_model)
Expand Down Expand Up @@ -598,8 +608,9 @@ def write_host_cap(host_model, api, module_name, output_dir, run_env):
const_names_name = constituent_model_const_stdnames(host_model)
const_indices_name = constituent_model_const_indices(host_model)
ConstituentVarDict.write_host_routines(cap, host_model, reg_name, init_name,
numconsts_name, copyin_name,
copyout_name, const_obj_name,
numconsts_name, queryconsts_name,
copyin_name, copyout_name,
const_obj_name,
const_names_name,
const_indices_name,
const_array_func,
Expand Down
2 changes: 2 additions & 0 deletions test/advection_test/cld_ice.meta
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
[ cld_ice_array ]
standard_name = cloud_ice_dry_mixing_ratio
advected = .true.
default_value = 0.0_kind_phys
units = kg kg-1
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
type = real | kind = kind_phys
Expand Down Expand Up @@ -76,6 +77,7 @@
[ cld_ice_array ]
standard_name = cloud_ice_dry_mixing_ratio
advected = .true.
default_value = 0.0_kind_phys
units = kg kg-1
dimensions = (horizontal_dimension, vertical_layer_dimension)
type = real | kind = kind_phys
Expand Down
90 changes: 83 additions & 7 deletions test/advection_test/test_host.F90
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ subroutine test_host(retval, test_suites)
use test_host_mod, only: init_data, compare_data
use test_host_mod, only: ncols, pver
use test_host_ccpp_cap, only: test_host_ccpp_register_constituents
use test_host_ccpp_cap, only: test_host_ccpp_is_scheme_constituent
use test_host_ccpp_cap, only: test_host_ccpp_initialize_constituents
use test_host_ccpp_cap, only: test_host_ccpp_number_constituents
use test_host_ccpp_cap, only: test_host_constituents_array
Expand All @@ -249,12 +250,15 @@ subroutine test_host(retval, test_suites)
integer :: num_suites
integer :: num_advected ! Num advected species
logical :: const_log
logical :: is_constituent
logical :: has_default
character(len=128), allocatable :: suite_names(:)
character(len=256) :: const_str
character(len=512) :: errmsg
integer :: errflg
integer :: errflg_final ! Used to notify testing script of test failure
real(kind_phys), pointer :: const_ptr(:,:,:)
real(kind_phys) :: default_value
type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:)
character(len=*), parameter :: subname = 'test_host'

Expand Down Expand Up @@ -289,8 +293,33 @@ subroutine test_host(retval, test_suites)
return
end if

! Register the constituents to find out what needs advecting
call host_constituents(1)%instantiate(std_name="specific_humidity", &
errflg = 0
errmsg = ''

! Check that is_scheme_constituent works as expected
call test_host_ccpp_is_scheme_constituent('specific_humidity', &
is_constituent, errflg, errmsg)
call check_errflg(subname//"_ccpp_is_scheme_constituent", errflg, &
errmsg, errflg_final)
! specific_humidity should not be an existing constituent
if (is_constituent) then
write(6, *) "ERROR: specific humidity is already a constituent"
errflg_final = -1 !Notify test script that a failure occurred
end if
call test_host_ccpp_is_scheme_constituent('cloud_ice_dry_mixing_ratio', &
is_constituent, errflg, errmsg)
call check_errflg(subname//"_ccpp_is_scheme_constituent", errflg, &
errmsg, errflg_final)
! cloud_ice_dry_mixing_ratio should be an existing constituent
if (.not. is_constituent) then
write(6, *) "ERROR: cloud_ice_dry_mixing ratio not found in ", &
"host cap constituent list"
errflg_final = -1 !Notify test script that a failure occurred
end if


! Register the constituents to find out what needs advecting
call host_constituents(1)%instantiate(std_name="specific_humidity", &
long_name="Specific humidity", units="kg kg-1", &
vertical_dim="vertical_layer_dimension", advected=.true., &
errcode=errflg, errmsg=errmsg)
Expand Down Expand Up @@ -422,7 +451,7 @@ subroutine test_host(retval, test_suites)
if (errflg /= 0) then
write(6, '(a,i0,a,a,i0,/,a)') "ERROR: Error, ", errflg, " trying ", &
"to get dry prop for cld_ice index = ", index_ice, trim(errmsg)
errflg_final = -1 !Notify test script that a failure occured
errflg_final = -1 !Notify test script that a failure occurred
nusbaume marked this conversation as resolved.
Show resolved Hide resolved
end if
if (errflg == 0) then
if (.not. const_log) then
Expand All @@ -440,7 +469,7 @@ subroutine test_host(retval, test_suites)
write(6, '(a,i0,a,a,i0,/,a)') "ERROR: Error, ", errflg, " trying ", &
"to get thermo_active prop for cld_ice index = ", index_ice, &
trim(errmsg)
errflg_final = -1 !Notify test script that a failure occured
errflg_final = -1 !Notify test script that a failure occurred
end if
if (errflg == 0) then
if (check) then !Should be False
Expand All @@ -460,28 +489,75 @@ subroutine test_host(retval, test_suites)
write(6, '(a,i0,a,a,i0,/,a)') "ERROR: Error, ", errflg, " trying ", &
"to set thermo_active prop for cld_ice index = ", index_ice, &
trim(errmsg)
errflg_final = -1 !Notify test script that a failure occured
errflg_final = -1 !Notify test script that a failure occurred
end if
if (errflg == 0) then
call const_props(index_ice)%is_thermo_active(check, errflg, errmsg)
if (errflg /= 0) then
write(6, '(a,i0,a,i0,/,a)') "ERROR: Error, ", errflg, &
" tryingto get thermo_active prop for cld_ice index = ", &
index_ice, trim(errmsg)
errflg_final = -1 !Notify test script that a failure occured
errflg_final = -1 !Notify test script that a failure occurred
end if
end if
if (errflg == 0) then
if (.not.check) then !Should now be True
write(6, *) "ERROR: 'set_thermo_active' did not set", &
" thermo_active constituent property correctly."
errflg_final = -1 !Notify test script that a failure occured
errflg_final = -1 !Notify test script that a failure occurred
end if
else
!Reset error flag to continue testing other properties:
errflg = 0
end if

!Check that setting a constituent's default value works as expected
call const_props(index_liq)%has_default(has_default, errflg, errmsg)
if (errflg /= 0) then
write(6, '(a,i0,2a,i0,/,a)') "ERROR: Error, ", errflg, " trying ", &
"to check for default for cld_liq index = ", index_liq, trim(errmsg)
errflg_final = -1 !Notify test script that a failure occurred
end if
if (errflg == 0) then
if (has_default) then
write(6, *) "ERROR: cloud liquid mass_mixing_ratio should not have default but does"
errflg_final = -1 !Notify test script that a failure occurred
end if
else
!Reset error flag to continue testing other properties:
errflg = 0
end if
call const_props(index_ice)%has_default(has_default, errflg, errmsg)
if (errflg /= 0) then
write(6, '(a,i0,2a,i0,/,a)') "ERROR: Error, ", errflg, " trying ", &
"to check for default for cld_ice index = ", index_ice, trim(errmsg)
errflg_final = -1 !Notify test script that a failure occurred
end if
if (errflg == 0) then
if (.not. has_default) then
write(6, *) "ERROR: cloud ice mass_mixing_ratio should have default but doesn't"
nusbaume marked this conversation as resolved.
Show resolved Hide resolved
errflg_final = -1 !Notify test script that a failure occurred
end if
else
!Reset error flag to continue testing other properties:
errflg = 0
end if
call const_props(index_ice)%default_value(default_value, errflg, errmsg)
if (errflg /= 0) then
write(6, '(a,i0,2a,i0,/,a)') "ERROR: Error, ", errflg, " trying ", &
"to grab default for cld_ice index = ", index_ice, trim(errmsg)
errflg_final = -1 !Notify test script that a failure occurred
end if
if (errflg == 0) then
if (default_value /= 0.0_kind_phys) then
write(6, *) "ERROR: cloud ice mass_mixing_ratio default is ", default_value, &
" but should be 0.0"
nusbaume marked this conversation as resolved.
Show resolved Hide resolved
errflg_final = -1 !Notify test script that a failure occurred
end if
else
!Reset error flag to continue testing other properties:
errflg = 0
end if
!++++++++++++++++++++++++++++++++++

!Set error flag to the "final" value, because any error
Expand Down