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

Added test using a DDT host object to pass information #591

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
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
94 changes: 57 additions & 37 deletions scripts/ccpp_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,9 +647,15 @@ def __init__(self, sdfs, host_model, scheme_headers, run_env):
# Secondary level is by phase
scheme_library = {}
# First, process DDT headers
all_ddts = [d for d in scheme_headers if d.header_type == 'ddt']
ddt_titles = [d.title for d in all_ddts]
for ddt_title in self.host_model.ddt_lib:
if ddt_title not in ddt_titles:
all_ddts.append(self.host_model.ddt_lib[ddt_title])
# end if
# end for
self.__ddt_lib = DDTLibrary('{}_api'.format(self.host_model.name),
run_env, ddts=[d for d in scheme_headers
if d.header_type == 'ddt'])
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, {}"
Expand Down Expand Up @@ -677,15 +683,14 @@ def __init__(self, sdfs, host_model, scheme_headers, run_env):
# end for
# We will need the correct names for errmsg and errcode
evar = self.host_model.find_variable(standard_name='ccpp_error_message')
subst_dict = {'intent':'out'}
if evar is not None:
self._errmsg_var = evar.clone(subst_dict)
self._errmsg_var = evar
else:
raise CCPPError('Required variable, ccpp_error_message, not found')
# end if
evar = self.host_model.find_variable(standard_name='ccpp_error_code')
if evar is not None:
self._errcode_var = evar.clone(subst_dict)
self._errcode_var = evar
else:
raise CCPPError('Required variable, ccpp_error_code, not found')
# end if
Expand Down Expand Up @@ -737,15 +742,25 @@ def write(self, output_dir, run_env):
@classmethod
def declare_inspection_interfaces(cls, ofile):
"""Declare the API interfaces for the suite inquiry functions"""
ofile.write("public :: {}".format(API.__suite_fname), 1)
ofile.write("public :: {}".format(API.__part_fname), 1)
ofile.write("public :: {}".format(API.__vars_fname), 1)
ofile.write("public :: {}".format(API.__schemes_fname), 1)

def get_errinfo_names(self):
"""Return a tuple of error output local names"""
errmsg_name = self._errmsg_var.get_prop_value('local_name')
errcode_name = self._errcode_var.get_prop_value('local_name')
ofile.write(f"public :: {API.__suite_fname}", 1)
ofile.write(f"public :: {API.__part_fname}", 1)
ofile.write(f"public :: {API.__vars_fname}", 1)
ofile.write(f"public :: {API.__schemes_fname}", 1)

def get_errinfo_names(self, base_only=False):
gold2718 marked this conversation as resolved.
Show resolved Hide resolved
"""Return a tuple of error output local names.
If base_only==True, return only the name string of the variable.
If base_only=False, return the local name as a full reference.
If the error variables are intrinsic variables, this makes no
difference, however, for a DDT variable, the full reference is
<ddt_name>%<errvar_name> while the local name is just <errvar_name>."""
if base_only:
errmsg_name = self._errmsg_var.get_prop_value('local_name')
errcode_name = self._errcode_var.get_prop_value('local_name')
else:
errmsg_name = self._errmsg_var.call_string(self)
errcode_name = self._errcode_var.call_string(self)
# end if
return (errmsg_name, errcode_name)

@staticmethod
Expand All @@ -756,29 +771,29 @@ def write_var_set_loop(ofile, varlist_name, var_list, indent,
beginning at <start_index>.
"""
if add_allocate:
ofile.write("allocate({}({}))".format(varlist_name, len(var_list)),
indent)
ofile.write(f"allocate({varlist_name}({len(var_list)}))", indent)
# end if
for ind, var in enumerate(sorted(var_list)):
if start_var:
ind_str = "{} + {}".format(start_var, ind + start_index)
ind_str = f"{start_var} + {ind + start_index}"
else:
ind_str = "{}".format(ind + start_index)
ind_str = f"{ind + start_index}"
# end if
ofile.write("{}({}) = '{}'".format(varlist_name, ind_str, var),
indent)
ofile.write(f"{varlist_name}({ind_str}) = '{var}'", indent)
# end for

def write_suite_part_list_sub(self, ofile, errmsg_name, errcode_name):
"""Write the suite-part list subroutine"""
inargs = f"suite_name, part_list, {errmsg_name}, {errcode_name}"
ofile.write(f"subroutine {API.__part_fname}({inargs})", 1)
oline = "character(len=*), intent(in) :: suite_name"
oline = "character(len=*), intent(in) :: suite_name"
ofile.write(oline, 2)
oline = "character(len=*), allocatable, intent(out) :: part_list(:)"
oline = "character(len=*), allocatable, intent(out) :: part_list(:)"
ofile.write(oline, 2)
self._errmsg_var.write_def(ofile, 2, self)
self._errcode_var.write_def(ofile, 2, self)
self._errmsg_var.write_def(ofile, 2, self, dummy=True, add_intent="out",
extra_space=11)
self._errcode_var.write_def(ofile, 2, self, dummy=True, add_intent="out",
extra_space=11)
else_str = ''
ename = self._errcode_var.get_prop_value('local_name')
ofile.write(f"{ename} = 0", 2)
Expand All @@ -805,17 +820,19 @@ def write_req_vars_sub(self, ofile, errmsg_name, errcode_name):
inargs = oline.format(errmsg=errmsg_name, errcode=errcode_name)
ofile.write("\nsubroutine {}({})".format(API.__vars_fname, inargs), 1)
ofile.write("! Dummy arguments", 2)
oline = "character(len=*), intent(in) :: suite_name"
oline = "character(len=*), intent(in) :: suite_name"
ofile.write(oline, 2)
oline = "character(len=*), allocatable, intent(out) :: variable_list(:)"
oline = "character(len=*), allocatable, intent(out) :: variable_list(:)"
ofile.write(oline, 2)
self._errmsg_var.write_def(ofile, 2, self, extra_space=22)
self._errcode_var.write_def(ofile, 2, self, extra_space=22)
oline = "logical, optional, intent(in) :: input_vars"
self._errmsg_var.write_def(ofile, 2, self, dummy=True,
add_intent="out", extra_space=11)
self._errcode_var.write_def(ofile, 2, self, dummy=True,
add_intent="out", extra_space=11)
oline = "logical, optional, intent(in) :: input_vars"
ofile.write(oline, 2)
oline = "logical, optional, intent(in) :: output_vars"
oline = "logical, optional, intent(in) :: output_vars"
ofile.write(oline, 2)
oline = "logical, optional, intent(in) :: struct_elements"
oline = "logical, optional, intent(in) :: struct_elements"
ofile.write(oline, 2)
ofile.write("! Local variables", 2)
ofile.write("logical {}:: input_vars_use".format(' '*34), 2)
Expand Down Expand Up @@ -1120,12 +1137,14 @@ def write_suite_schemes_sub(self, ofile, errmsg_name, errcode_name):
inargs = oline.format(errmsg=errmsg_name, errcode=errcode_name)
ofile.write("\nsubroutine {}({})".format(API.__schemes_fname,
inargs), 1)
oline = "character(len=*), intent(in) :: suite_name"
oline = "character(len=*), intent(in) :: suite_name"
ofile.write(oline, 2)
oline = "character(len=*), allocatable, intent(out) :: scheme_list(:)"
oline = "character(len=*), allocatable, intent(out) :: scheme_list(:)"
ofile.write(oline, 2)
self._errmsg_var.write_def(ofile, 2, self)
self._errcode_var.write_def(ofile, 2, self)
self._errmsg_var.write_def(ofile, 2, self, dummy=True,
add_intent="out", extra_space=11)
self._errcode_var.write_def(ofile, 2, self, dummy=True,
add_intent="out", extra_space=11)
else_str = ''
ename = self._errcode_var.get_prop_value('local_name')
ofile.write("{} = 0".format(ename), 2)
Expand Down Expand Up @@ -1153,16 +1172,17 @@ def write_suite_schemes_sub(self, ofile, errmsg_name, errcode_name):

def write_inspection_routines(self, ofile):
"""Write the list_suites and list_suite_parts subroutines"""
errmsg_name, errcode_name = self.get_errinfo_names()
errmsg_name, errcode_name = self.get_errinfo_names(base_only=True)
ofile.write("subroutine {}(suites)".format(API.__suite_fname), 1)
nsuites = len(self.suites)
oline = "character(len=*), allocatable, intent(out) :: suites(:)"
oline = "character(len=*), allocatable, intent(out) :: suites(:)"
ofile.write(oline, 2)
ofile.write("\nallocate(suites({}))".format(nsuites), 2)
for ind, suite in enumerate(self.suites):
ofile.write("suites({}) = '{}'".format(ind+1, suite.name), 2)
# end for
ofile.write("end subroutine {}".format(API.__suite_fname), 1)
ofile.blank_line()
# Write out the suite part list subroutine
self.write_suite_part_list_sub(ofile, errmsg_name, errcode_name)
# Write out the suite required variable subroutine
Expand Down
10 changes: 6 additions & 4 deletions scripts/constituents.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,10 +491,11 @@ def write_host_routines(cap, host, reg_funcname, init_funcname, num_const_funcna
ConstituentVarDict.write_constituent_use_statements(cap, suite_list, 2)
cap.blank_line()
cap.comment("Dummy arguments", 2)
cap.write(f"type({CONST_PROP_TYPE}), target, intent(in) :: " + \
cap.write(f"type({CONST_PROP_TYPE}), target, intent(in) :: " + \
"host_constituents(:)", 2)
for evar in err_vars:
evar.write_def(cap, 2, host, dummy=True, add_intent="out")
evar.write_def(cap, 2, host, dummy=True,
add_intent="out", extra_space=25)
# end for
cap.comment("Local variables", 2)
spc = ' '*37
Expand Down Expand Up @@ -546,7 +547,7 @@ def write_host_routines(cap, host, reg_funcname, init_funcname, num_const_funcna
cap.write("end if", 3)
cap.write("end do", 2)
# end for

# Register suite constituents
for suite in suite_list:
errvar_str = ConstituentVarDict.__errcode_callstr(herrcode,
Expand Down Expand Up @@ -745,7 +746,8 @@ def write_host_routines(cap, host, reg_funcname, init_funcname, num_const_funcna
cap.write("character(len=*), intent(in) :: stdname", 2)
cap.write("integer, intent(out) :: const_index", 2)
for evar in err_vars:
evar.write_def(cap, 2, host, dummy=True, add_intent="out")
evar.write_def(cap, 2, host, dummy=True,
add_intent="out", extra_space=1)
# end for
cap.blank_line()
cap.write(f"call {const_obj_name}%const_index(const_index, " + \
Expand Down
22 changes: 16 additions & 6 deletions scripts/ddt_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,21 @@ def call_string(self, var_dict, loop_vars=None):
# end if
return call_str

def write_def(self, outfile, indent, ddict, allocatable=False, dummy=False):
def write_def(self, outfile, indent, ddict, allocatable=False, target=False,
dummy=False, add_intent=None, extra_space=0, public=False):
"""Write the definition line for this DDT.
The type of this declaration is the type of the Var at the
end of the chain of references."""
if self.field is None:
super().write_def(outfile, indent, ddict,
allocatable=allocatable, dummy=dummy)
allocatable=allocatable, target=target, dummy=dummy,
add_intent=add_intent, extra_space=extra_space,
public=public)
else:
self.field.write_def(outfile, indent, ddict,
allocatable=allocatable, dummy=dummy)
allocatable=allocatable, target=target,
dummy=dummy, add_intent=add_intent,
extra_space=extra_space, public=public)
# end if

@staticmethod
Expand Down Expand Up @@ -214,8 +219,8 @@ def __init__(self, name, run_env, ddts=None):
# end if
if ddt.title in self:
errmsg = "Duplicate DDT, {}, found{}, original{}"
ctx = context_string(ddt.source.context)
octx = context_string(self[ddt.title].source.context)
ctx = context_string(ddt.context)
octx = context_string(self[ddt.title].context)
raise CCPPError(errmsg.format(ddt.title, ctx, octx))
# end if
if run_env.verbose:
Expand Down Expand Up @@ -324,14 +329,19 @@ def write_ddt_use_statements(self, variable_list, outfile, indent, pad=0):

@property
def name(self):
"Return the name of this DDT library"
"""Return the name of this DDT library"""
return self.__name

@property
def run_env(self):
"""Return the CCPPFrameworkEnv object for this DDT library"""
return self.__run_env

@property
def max_mod_name_len(self):
"""Return the maximum module name length of this DDT library's modules"""
return self.__max_mod_name_len

###############################################################################
if __name__ == "__main__":
# pylint: disable=ungrouped-imports
Expand Down
14 changes: 7 additions & 7 deletions scripts/host_cap.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,12 +523,12 @@ def suite_part_call_list(host_model, const_dict, suite_part, subst_loop_vars,
# end if
# end for
if hvar is None:
errmsg = 'No host model variable for {} in {}'
raise CCPPError(errmsg.format(stdname, suite_part.name))
errmsg = f"No host model variable for {stdname} in {suite_part.name}"
raise CCPPError(errmsg)
# End if
if stdname not in CCPP_CONSTANT_VARS:
lname = var_dict.var_call_string(hvar, loop_vars=loop_vars)
hmvars.append("{}={}".format(sp_lname, lname))
hmvars.append(f"{sp_lname}={lname}")
# End if
# End for
return ', '.join(hmvars)
Expand Down Expand Up @@ -563,7 +563,7 @@ def write_host_cap(host_model, api, module_name, output_dir, run_env):
cap.write(f"use {CONST_DDT_MOD}, {mspc}only: {CONST_DDT_NAME}", 1)
cap.write(f"use {CONST_DDT_MOD}, {mspc}only: {CONST_PROP_TYPE}", 1)
cap.write_preamble()
max_suite_len = 0
max_suite_len = host_model.ddt_lib.max_mod_name_len
for suite in api.suites:
max_suite_len = max(max_suite_len, len(suite.module))
# End for
Expand Down Expand Up @@ -697,12 +697,12 @@ def write_host_cap(host_model, api, module_name, output_dir, run_env):
pad=max_suite_len)

cap.write("", 1)
# Write out dummy arguments
# Write out dummy argument definitions
for var in apivars:
var.write_def(cap, 2, host_model)
var.write_def(cap, 2, host_model, dummy=True)
# End for
for var in hdvars:
var.write_def(cap, 2, host_model)
var.write_def(cap, 2, host_model, dummy=True)
# End for
for var in host_local_vars.variable_list():
var.write_def(cap, 2, host_model,
Expand Down
3 changes: 3 additions & 0 deletions scripts/host_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ def __init__(self, meta_tables, name_in, run_env):
# End for
loop_vars = header.variable_list(std_vars=False,
loop_vars=True, consts=False)
loop_vars.extend(self.__ddt_dict.variable_list(std_vars=False,
loop_vars=True,
consts=False))
if loop_vars:
# loop_vars are part of the host-model interface call
# at run time. As such, they override the host-model
Expand Down
Loading
Loading