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

Allow registry fields with initial_value to not error on not found in input data #365

Merged
merged 5 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from 4 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
12 changes: 7 additions & 5 deletions cime_config/cam_autogen.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def generate_registry(data_search, build_cache, atm_root, bldroot,
gen_fort_indent, source_mods_dir, atm_root,
logger=_LOGGER, schema_paths=data_search,
error_on_no_validate=True)
retcode, reg_file_list, ic_names, registry_constituents = retvals
retcode, reg_file_list, ic_names, registry_constituents, vars_init_value = retvals
# Raise error if gen_registry failed:
if retcode != 0:
emsg = "ERROR:Unable to generate CAM data structures from {}, err = {}"
Expand All @@ -406,15 +406,16 @@ def generate_registry(data_search, build_cache, atm_root, bldroot,
# Save build details in the build cache
reg_file_paths = [x.file_path for x in reg_file_list if x.file_path]
build_cache.update_registry(gen_reg_file, registry_files, dycore,
reg_file_paths, ic_names, registry_constituents)
reg_file_paths, ic_names, registry_constituents, vars_init_value)
else:
# If we did not run the registry generator, retrieve info from cache
reg_file_paths = build_cache.reg_file_list()
ic_names = build_cache.ic_names()
registry_constituents = build_cache.constituents()
vars_init_value = build_cache.vars_init_value()
# End if

return genreg_dir, do_gen_registry, reg_file_paths, ic_names, registry_constituents
return genreg_dir, do_gen_registry, reg_file_paths, ic_names, registry_constituents, vars_init_value

###############################################################################
def generate_physics_suites(build_cache, preproc_defs, host_name,
Expand Down Expand Up @@ -659,7 +660,8 @@ def generate_physics_suites(build_cache, preproc_defs, host_name,
###############################################################################
def generate_init_routines(build_cache, bldroot, force_ccpp, force_init,
source_mods_dir, gen_fort_indent,
cap_database, ic_names, registry_constituents):
cap_database, ic_names, registry_constituents,
vars_init_value):
###############################################################################
"""
Generate the host model initialization source code files
Expand Down Expand Up @@ -697,7 +699,7 @@ def generate_init_routines(build_cache, bldroot, force_ccpp, force_init,
# within write_init_files (so that write_init_files can be the place
# where the source include files are stored).
source_paths = [source_mods_dir, _REG_GEN_DIR]
retmsg = write_init_files(cap_database, ic_names, registry_constituents,
retmsg = write_init_files(cap_database, ic_names, registry_constituents, vars_init_value,
init_dir, _find_file, source_paths,
gen_fort_indent, _LOGGER)

Expand Down
14 changes: 13 additions & 1 deletion cime_config/cam_build_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ def __init__(self, build_cache):
self.__reg_gen_files = []
self.__ic_names = {}
self.__constituents = []
self.__vars_init_value = []
if os.path.exists(build_cache):
# Initialize build cache state
_, cache = read_xml_file(build_cache)
Expand Down Expand Up @@ -257,6 +258,9 @@ def __init__(self, build_cache):
stdname = item.get('standard_name')
itext = clean_xml_text(item)
self.__constituents.append(itext)
elif item.tag == 'vars_init_value_entry':
itext = clean_xml_text(item)
self.__vars_init_value.append(itext)
else:
emsg = "ERROR: Unknown registry tag, '{}'"
raise ValueError(emsg.format(item.tag))
Expand Down Expand Up @@ -318,7 +322,7 @@ def __init__(self, build_cache):
# end if

def update_registry(self, gen_reg_file, registry_source_files,
dycore, reg_file_list, ic_names, constituents):
dycore, reg_file_list, ic_names, constituents, vars_init_value):
"""Replace the registry cache data with input data
"""
self.__dycore = dycore
Expand All @@ -334,6 +338,7 @@ def update_registry(self, gen_reg_file, registry_source_files,
# and should already be of type dict:
self.__ic_names = ic_names
self.__constituents = constituents
self.__vars_init_value = vars_init_value

def update_ccpp(self, suite_definition_files, scheme_files, host_files,
xml_files, namelist_meta_files, namelist_groups,
Expand Down Expand Up @@ -410,6 +415,9 @@ def write(self):
const_entry = ET.SubElement(registry, 'constituent_entry')
const_entry.text = stdname
# end for
for stdname in self.__vars_init_value:
var_entry = ET.SubElement(registry, 'vars_init_value_entry')
var_entry.text = stdname
# CCPP
ccpp = ET.SubElement(new_cache, 'CCPP')
for sfile in self.__sdfs.values():
Expand Down Expand Up @@ -617,5 +625,9 @@ def constituents(self):
"""Return a copy of the registry constituents list"""
return list(self.__constituents)

def vars_init_value(self):
"""Return a copy of the list of variables with initial_value"""
return list(self.__vars_init_value)

#############
# End of file
5 changes: 3 additions & 2 deletions cime_config/cam_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ def generate_cam_src(self, gen_fort_indent):
retvals = generate_registry(data_search, build_cache, self.__atm_root,
self.__bldroot, source_mods_dir,
dyn, gen_fort_indent)
reg_dir, force_ccpp, reg_files, ic_names, registry_constituents = retvals
reg_dir, force_ccpp, reg_files, ic_names, registry_constituents, vars_init_value = retvals

#Add registry path to config object:
reg_dir_desc = "Location of auto-generated registry code."
Expand Down Expand Up @@ -887,7 +887,8 @@ def generate_cam_src(self, gen_fort_indent):
init_dir = generate_init_routines(build_cache, self.__bldroot,
force_ccpp, force_init,
source_mods_dir, gen_fort_indent,
capgen_db, ic_names, registry_constituents)
capgen_db, ic_names, registry_constituents,
vars_init_value)

#Add registry path to config object:
init_dir_desc = "Location of auto-generated physics initialization code."
Expand Down
32 changes: 29 additions & 3 deletions src/data/generate_registry_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,30 @@ def _create_constituent_list(registry):
# end for
return constituent_list

###############################################################################
def _create_variables_with_initial_value_list(registry):
###############################################################################
"""
Create a list of all variables with initial_value defined in the registry.
To be used by write_init_files.py to allow these variables to
not error when not found in the initial conditions file.
"""
vars_init_value_list = []
for section in registry:
if section.tag == 'file':
for obj in section:
if obj.tag == 'variable':
for subobj in obj:
if subobj.tag == 'initial_value':
stdname = obj.get('standard_name')
vars_init_value_list.append(stdname)
# end if (only if initial_value node is found)
# end for
# end if (ignore other node types)
# end for
# end if (ignore other node types)
# end for
return vars_init_value_list

###############################################################################
def gen_registry(registry_file, dycore, outdir, indent,
Expand All @@ -1767,7 +1791,7 @@ def gen_registry(registry_file, dycore, outdir, indent,
"""Parse a registry XML file and generate source code and metadata.
<dycore> is the name of the dycore for DP coupling specialization.
<config> is a dictionary containing other configuration items for
souce code customization.
source code customization.
Source code and metadata is output to <outdir>.
<src_mod> is the location of the builds SourceMods/src.cam directory
<src_root> is the top of the component tree
Expand Down Expand Up @@ -1819,7 +1843,8 @@ def gen_registry(registry_file, dycore, outdir, indent,
retcode = 1
files = None
ic_names = None
constituents = None
registry_constituents = None
vars_init_value = None
else:
library_name = registry.get('name')
emsg = f"Parsing registry, {library_name}"
Expand All @@ -1830,9 +1855,10 @@ def gen_registry(registry_file, dycore, outdir, indent,
# See comment in _create_ic_name_dict
ic_names = _create_ic_name_dict(registry)
registry_constituents = _create_constituent_list(registry)
vars_init_value = _create_variables_with_initial_value_list(registry)
retcode = 0 # Throw exception on error
# end if
return retcode, files, ic_names, registry_constituents
return retcode, files, ic_names, registry_constituents, vars_init_value

def main():
"""Function to execute when module called as a script"""
Expand Down
23 changes: 18 additions & 5 deletions src/data/write_init_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
#Main function
##############

def write_init_files(cap_database, ic_names, registry_constituents, outdir,
def write_init_files(cap_database, ic_names, registry_constituents, vars_init_value,
outdir,
file_find_func, source_paths, indent, logger,
phys_check_filename=None, phys_input_filename=None):
Copy link
Collaborator

@nusbaume nusbaume Feb 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spacing looks a little strange here, maybe do something like this instead (?):

Suggested change
def write_init_files(cap_database, ic_names, registry_constituents, vars_init_value,
outdir,
file_find_func, source_paths, indent, logger,
phys_check_filename=None, phys_input_filename=None):
def write_init_files(cap_database, ic_names, registry_constituents, vars_init_value,
outdir, file_find_func, source_paths, indent, logger,
phys_check_filename=None, phys_input_filename=None):

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, updated!


Expand Down Expand Up @@ -239,7 +240,8 @@ def write_init_files(cap_database, ic_names, registry_constituents, outdir,

# Write physics_read_data subroutine:
write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
phys_check_fname_str, constituent_set)
phys_check_fname_str, constituent_set,
vars_init_value)

outfile.blank_line()

Expand Down Expand Up @@ -810,7 +812,8 @@ def get_dimension_info(hvar):
return vdim_name, legal_dims, fail_reason

def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
phys_check_fname_str, constituent_set):
phys_check_fname_str, constituent_set,
vars_init_value):

"""
Write the "physics_read_data" subroutine, which
Expand Down Expand Up @@ -866,10 +869,20 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
if levnm is not None:
call_str += f"'{levnm}', "
# end if
call_str += f"timestep, {var_locname})"
err_on_not_found_string = ""
if var_stdname in vars_init_value:
# if initial value is available, do not throw error when not found in initial condition file.
err_on_not_found_string = ", error_on_not_found=.false."
# end if
call_str += f"timestep, {var_locname}{err_on_not_found_string})"
else:
call_str = f"call endrun('Cannot read {var_locname} from file'" + \
# if initial value is assigned, then it can be ignored
if var_stdname in vars_init_value:
call_str = f"if(masterproc) write(iulog,*) '{var_locname} already has an initial_value, using it now. It also cannot be read from file: {reason}'"
else:
call_str = f"call endrun('Cannot read {var_locname} from file'" + \
f"//', {reason}')"
# end if
# end if

# Add string to dictionary:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<ic_name_entry standard_name="Only_had_a">brain</ic_name_entry>
<constituent_entry>cnst_1</constituent_entry>
<constituent_entry>cnst_2</constituent_entry>
<vars_init_value_entry>Only_had_a_brain</vars_init_value_entry>
</registry>
<CCPP>
<SDF file_path="/behind/curtain/suite_wizard.xml" hash="ade45dea32a6f279957735596a147efddd061f9c"/>
Expand Down
Loading