Skip to content

Commit 8284094

Browse files
committed
Merge branch 'development' into hplin/hk_conv_rebase
2 parents a8cadbe + a244a84 commit 8284094

19 files changed

+1397
-344
lines changed

cime_config/buildlib

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,28 +147,40 @@ def _build_cam():
147147
# build the library
148148
#-------------------------------------------------------
149149

150-
# If dynamical core is MPAS, setup its build infrastructure so it can be built along with CAM below.
151-
if dycore == "mpas":
152-
_setup_mpas(case)
153-
154150
complib = os.path.join(libroot, "libatm.a")
155151
makefile = os.path.join(casetools, "Makefile")
156152

157153
cmd = f"{gmake} complib -j {gmake_j} MODEL=cam COMPLIB={complib}"
158-
cmd += f" -f {makefile} {get_standard_makefile_args(case)} "
154+
cmd += f" -f {makefile} {get_standard_makefile_args(case)}"
159155

160156
# Add C Pre-Processor (CPP) definitions, if present:
161157
if config.cpp_defs:
162158
ccpp_defs_str = ' '.join(config.cpp_defs)
163159
cmd += f" USER_CPPDEFS='{ccpp_defs_str}'"
164160

161+
# If dynamical core is MPAS, prepare its build infrastructure so it can be built along with CAM-SIMA below.
162+
if dycore == "mpas":
163+
_prepare_mpas(case)
164+
165+
optional_mpas_features = []
166+
167+
if case.get_value("USE_ESMF_LIB"):
168+
optional_mpas_features.append("+ESMF_LIBRARY")
169+
optional_mpas_features.append("+PERF_MOD_LIBRARY")
170+
171+
if config.get_value("dyn_kind") == "REAL32":
172+
optional_mpas_features.append("+SINGLE_PRECISION")
173+
174+
if len(optional_mpas_features) > 0:
175+
cmd += " OPTIONAL_MPAS_FEATURES=\"" + " ".join(optional_mpas_features) + "\""
176+
165177
retcode, out, err = run_cmd(cmd)
166-
_LOGGER.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n", cmd, out, err)
178+
_LOGGER.info("Command %s:\n\nstdout:\n%s\n\nstderr:\n%s\n", cmd, out, err)
167179
expect(retcode == 0, f"Command {cmd} failed with rc={retcode}")
168180

169-
def _setup_mpas(case: Case) -> None:
181+
def _prepare_mpas(case: Case) -> None:
170182
"""
171-
Setup MPAS build infrastructure.
183+
Prepare MPAS build infrastructure.
172184
"""
173185

174186
atm_src_root = os.path.normpath(case.get_value("COMP_ROOT_DIR_ATM"))
@@ -177,7 +189,7 @@ def _setup_mpas(case: Case) -> None:
177189
mpas_dycore_src_root = os.path.join(atm_src_root, "src", "dynamics", "mpas", "dycore", "src")
178190
mpas_dycore_bld_root = os.path.join(atm_bld_root, "mpas")
179191

180-
# Make sure `mpas_dycore_src_root` exists. If not, it is likely that `./manage_externals/checkout_externals` did not succeed.
192+
# Make sure `mpas_dycore_src_root` exists. If not, it is likely that `./bin/git-fleximod update` did not succeed.
181193
if os.path.isfile(mpas_dycore_src_root):
182194
raise FileExistsError(1, "Unexpected file", mpas_dycore_src_root)
183195

cime_config/cam_autogen.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ def generate_registry(data_search, build_cache, atm_root, bldroot,
392392
gen_fort_indent, source_mods_dir, atm_root,
393393
logger=_LOGGER, schema_paths=data_search,
394394
error_on_no_validate=True)
395-
retcode, reg_file_list, ic_names, registry_constituents = retvals
395+
retcode, reg_file_list, ic_names, registry_constituents, vars_init_value = retvals
396396
# Raise error if gen_registry failed:
397397
if retcode != 0:
398398
emsg = "ERROR:Unable to generate CAM data structures from {}, err = {}"
@@ -406,15 +406,16 @@ def generate_registry(data_search, build_cache, atm_root, bldroot,
406406
# Save build details in the build cache
407407
reg_file_paths = [x.file_path for x in reg_file_list if x.file_path]
408408
build_cache.update_registry(gen_reg_file, registry_files, dycore,
409-
reg_file_paths, ic_names, registry_constituents)
409+
reg_file_paths, ic_names, registry_constituents, vars_init_value)
410410
else:
411411
# If we did not run the registry generator, retrieve info from cache
412412
reg_file_paths = build_cache.reg_file_list()
413413
ic_names = build_cache.ic_names()
414414
registry_constituents = build_cache.constituents()
415+
vars_init_value = build_cache.vars_init_value()
415416
# End if
416417

417-
return genreg_dir, do_gen_registry, reg_file_paths, ic_names, registry_constituents
418+
return genreg_dir, do_gen_registry, reg_file_paths, ic_names, registry_constituents, vars_init_value
418419

419420
###############################################################################
420421
def generate_physics_suites(build_cache, preproc_defs, host_name,
@@ -659,7 +660,8 @@ def generate_physics_suites(build_cache, preproc_defs, host_name,
659660
###############################################################################
660661
def generate_init_routines(build_cache, bldroot, force_ccpp, force_init,
661662
source_mods_dir, gen_fort_indent,
662-
cap_database, ic_names, registry_constituents):
663+
cap_database, ic_names, registry_constituents,
664+
vars_init_value):
663665
###############################################################################
664666
"""
665667
Generate the host model initialization source code files
@@ -697,7 +699,7 @@ def generate_init_routines(build_cache, bldroot, force_ccpp, force_init,
697699
# within write_init_files (so that write_init_files can be the place
698700
# where the source include files are stored).
699701
source_paths = [source_mods_dir, _REG_GEN_DIR]
700-
retmsg = write_init_files(cap_database, ic_names, registry_constituents,
702+
retmsg = write_init_files(cap_database, ic_names, registry_constituents, vars_init_value,
701703
init_dir, _find_file, source_paths,
702704
gen_fort_indent, _LOGGER)
703705

cime_config/cam_build_cache.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ def __init__(self, build_cache):
227227
self.__reg_gen_files = []
228228
self.__ic_names = {}
229229
self.__constituents = []
230+
self.__vars_init_value = []
230231
if os.path.exists(build_cache):
231232
# Initialize build cache state
232233
_, cache = read_xml_file(build_cache)
@@ -257,6 +258,9 @@ def __init__(self, build_cache):
257258
stdname = item.get('standard_name')
258259
itext = clean_xml_text(item)
259260
self.__constituents.append(itext)
261+
elif item.tag == 'vars_init_value_entry':
262+
itext = clean_xml_text(item)
263+
self.__vars_init_value.append(itext)
260264
else:
261265
emsg = "ERROR: Unknown registry tag, '{}'"
262266
raise ValueError(emsg.format(item.tag))
@@ -318,7 +322,7 @@ def __init__(self, build_cache):
318322
# end if
319323

320324
def update_registry(self, gen_reg_file, registry_source_files,
321-
dycore, reg_file_list, ic_names, constituents):
325+
dycore, reg_file_list, ic_names, constituents, vars_init_value):
322326
"""Replace the registry cache data with input data
323327
"""
324328
self.__dycore = dycore
@@ -334,6 +338,7 @@ def update_registry(self, gen_reg_file, registry_source_files,
334338
# and should already be of type dict:
335339
self.__ic_names = ic_names
336340
self.__constituents = constituents
341+
self.__vars_init_value = vars_init_value
337342

338343
def update_ccpp(self, suite_definition_files, scheme_files, host_files,
339344
xml_files, namelist_meta_files, namelist_groups,
@@ -410,6 +415,9 @@ def write(self):
410415
const_entry = ET.SubElement(registry, 'constituent_entry')
411416
const_entry.text = stdname
412417
# end for
418+
for stdname in self.__vars_init_value:
419+
var_entry = ET.SubElement(registry, 'vars_init_value_entry')
420+
var_entry.text = stdname
413421
# CCPP
414422
ccpp = ET.SubElement(new_cache, 'CCPP')
415423
for sfile in self.__sdfs.values():
@@ -617,5 +625,9 @@ def constituents(self):
617625
"""Return a copy of the registry constituents list"""
618626
return list(self.__constituents)
619627

628+
def vars_init_value(self):
629+
"""Return a copy of the list of variables with initial_value"""
630+
return list(self.__vars_init_value)
631+
620632
#############
621633
# End of file

cime_config/cam_config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,7 @@ def generate_cam_src(self, gen_fort_indent):
854854
retvals = generate_registry(data_search, build_cache, self.__atm_root,
855855
self.__bldroot, source_mods_dir,
856856
dyn, gen_fort_indent)
857-
reg_dir, force_ccpp, reg_files, ic_names, registry_constituents = retvals
857+
reg_dir, force_ccpp, reg_files, ic_names, registry_constituents, vars_init_value = retvals
858858

859859
#Add registry path to config object:
860860
reg_dir_desc = "Location of auto-generated registry code."
@@ -887,7 +887,8 @@ def generate_cam_src(self, gen_fort_indent):
887887
init_dir = generate_init_routines(build_cache, self.__bldroot,
888888
force_ccpp, force_init,
889889
source_mods_dir, gen_fort_indent,
890-
capgen_db, ic_names, registry_constituents)
890+
capgen_db, ic_names, registry_constituents,
891+
vars_init_value)
891892

892893
#Add registry path to config object:
893894
init_dir_desc = "Location of auto-generated physics initialization code."

src/data/generate_registry_data.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,30 @@ def _create_constituent_list(registry):
17581758
# end for
17591759
return constituent_list
17601760

1761+
###############################################################################
1762+
def _create_variables_with_initial_value_list(registry):
1763+
###############################################################################
1764+
"""
1765+
Create a list of all variables with initial_value defined in the registry.
1766+
To be used by write_init_files.py to allow these variables to
1767+
not error when not found in the initial conditions file.
1768+
"""
1769+
vars_init_value_list = []
1770+
for section in registry:
1771+
if section.tag == 'file':
1772+
for obj in section:
1773+
if obj.tag == 'variable':
1774+
for subobj in obj:
1775+
if subobj.tag == 'initial_value':
1776+
stdname = obj.get('standard_name')
1777+
vars_init_value_list.append(stdname)
1778+
# end if (only if initial_value node is found)
1779+
# end for
1780+
# end if (ignore other node types)
1781+
# end for
1782+
# end if (ignore other node types)
1783+
# end for
1784+
return vars_init_value_list
17611785

17621786
###############################################################################
17631787
def gen_registry(registry_file, dycore, outdir, indent,
@@ -1767,7 +1791,7 @@ def gen_registry(registry_file, dycore, outdir, indent,
17671791
"""Parse a registry XML file and generate source code and metadata.
17681792
<dycore> is the name of the dycore for DP coupling specialization.
17691793
<config> is a dictionary containing other configuration items for
1770-
souce code customization.
1794+
source code customization.
17711795
Source code and metadata is output to <outdir>.
17721796
<src_mod> is the location of the builds SourceMods/src.cam directory
17731797
<src_root> is the top of the component tree
@@ -1819,7 +1843,8 @@ def gen_registry(registry_file, dycore, outdir, indent,
18191843
retcode = 1
18201844
files = None
18211845
ic_names = None
1822-
constituents = None
1846+
registry_constituents = None
1847+
vars_init_value = None
18231848
else:
18241849
library_name = registry.get('name')
18251850
emsg = f"Parsing registry, {library_name}"
@@ -1830,9 +1855,10 @@ def gen_registry(registry_file, dycore, outdir, indent,
18301855
# See comment in _create_ic_name_dict
18311856
ic_names = _create_ic_name_dict(registry)
18321857
registry_constituents = _create_constituent_list(registry)
1858+
vars_init_value = _create_variables_with_initial_value_list(registry)
18331859
retcode = 0 # Throw exception on error
18341860
# end if
1835-
return retcode, files, ic_names, registry_constituents
1861+
return retcode, files, ic_names, registry_constituents, vars_init_value
18361862

18371863
def main():
18381864
"""Function to execute when module called as a script"""

src/data/write_init_files.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@
4747
#Main function
4848
##############
4949

50-
def write_init_files(cap_database, ic_names, registry_constituents, outdir,
51-
file_find_func, source_paths, indent, logger,
50+
def write_init_files(cap_database, ic_names, registry_constituents, vars_init_value,
51+
outdir, file_find_func, source_paths, indent, logger,
5252
phys_check_filename=None, phys_input_filename=None):
5353

5454
"""
@@ -239,7 +239,8 @@ def write_init_files(cap_database, ic_names, registry_constituents, outdir,
239239

240240
# Write physics_read_data subroutine:
241241
write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
242-
phys_check_fname_str, constituent_set)
242+
phys_check_fname_str, constituent_set,
243+
vars_init_value)
243244

244245
outfile.blank_line()
245246

@@ -810,7 +811,8 @@ def get_dimension_info(hvar):
810811
return vdim_name, legal_dims, fail_reason
811812

812813
def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
813-
phys_check_fname_str, constituent_set):
814+
phys_check_fname_str, constituent_set,
815+
vars_init_value):
814816

815817
"""
816818
Write the "physics_read_data" subroutine, which
@@ -866,10 +868,20 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
866868
if levnm is not None:
867869
call_str += f"'{levnm}', "
868870
# end if
869-
call_str += f"timestep, {var_locname})"
871+
err_on_not_found_string = ""
872+
if var_stdname in vars_init_value:
873+
# if initial value is available, do not throw error when not found in initial condition file.
874+
err_on_not_found_string = ", error_on_not_found=.false."
875+
# end if
876+
call_str += f"timestep, {var_locname}{err_on_not_found_string})"
870877
else:
871-
call_str = f"call endrun('Cannot read {var_locname} from file'" + \
878+
# if initial value is assigned, then it can be ignored
879+
if var_stdname in vars_init_value:
880+
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}'"
881+
else:
882+
call_str = f"call endrun('Cannot read {var_locname} from file'" + \
872883
f"//', {reason}')"
884+
# end if
873885
# end if
874886

875887
# Add string to dictionary:

0 commit comments

Comments
 (0)