From fd886c14ad8fb14e57e4d6707569a5ad825ddac1 Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Mon, 2 Dec 2024 13:11:47 -0700 Subject: [PATCH] read in all possible constituents from file, not just build-time ones (#301) Tag name (required for release branches): Originator(s): peverwhee Summary (include the keyword ['closes', 'fixes', 'resolves'] and issue number): - Updates to enable reading in data for runtime constituents Describe any changes made to build system: M cime_config/cam_autogen.py M cime_config/cam_build_cache.py M cime_config/cam_config.py - keep track of registry constituents Describe any changes made to the namelist: None List any changes to the defaults for the input datasets (e.g. boundary datasets): None List all files eliminated and why: None List all files added and what they do: None List all existing files that have been modified, and describe the changes: (Helpful git command: `git diff --name-status development...`) M src/data/generate_registry_data.py - create list of registry constituents to pass to write_init_files M src/data/write_init_files.py - handle constituents separately from other host variables; read/check ALL constituent variables, not just "required" ones M test/unit/test_*.py - update calling lists If there are new failures (compare to the `test/existing-test-failures.txt` file), have them OK'd by the gatekeeper, note them here, and add them to the file. If there are baseline differences, include the test and the reason for the diff. What is the nature of the change? Roundoff? derecho/intel/aux_sima: derecho/gnu/aux_sima: If this changes climate describe any run(s) done to evaluate the new climate in enough detail that it(they) could be reproduced: CAM-SIMA date used for the baseline comparison tests if different than latest: --------- Co-authored-by: Courtney Peverley --- .gitmodules | 2 +- cime_config/cam_autogen.py | 16 +- cime_config/cam_build_cache.py | 16 +- cime_config/cam_config.py | 4 +- src/data/air_composition.F90 | 6 +- src/data/generate_registry_data.py | 29 ++- src/data/registry.xml | 12 + src/data/write_init_files.py | 230 ++++++++++++------ src/physics/ncar_ccpp | 2 +- .../update_reg_build_cache.xml | 2 + .../phys_vars_init_check_cnst.F90 | 10 +- .../write_init_files/physics_inputs_4D.F90 | 178 ++++++++------ .../write_init_files/physics_inputs_bvd.F90 | 152 +++++++----- .../write_init_files/physics_inputs_cnst.F90 | 152 +++++++----- .../write_init_files/physics_inputs_ddt.F90 | 178 ++++++++------ .../write_init_files/physics_inputs_ddt2.F90 | 152 +++++++----- .../physics_inputs_ddt_array.F90 | 152 +++++++----- .../physics_inputs_host_var.F90 | 152 +++++++----- .../write_init_files/physics_inputs_mf.F90 | 180 ++++++++------ .../physics_inputs_no_horiz.F90 | 152 +++++++----- .../write_init_files/physics_inputs_noreq.F90 | 152 +++++++----- .../write_init_files/physics_inputs_param.F90 | 152 +++++++----- .../physics_inputs_protect.F90 | 152 +++++++----- .../physics_inputs_scalar.F90 | 152 +++++++----- .../physics_inputs_simple.F90 | 152 +++++++----- test/unit/test_build_cache.py | 4 +- test/unit/test_cam_autogen.py | 8 +- test/unit/test_registry.py | 18 +- test/unit/test_write_init_files.py | 42 ++-- 29 files changed, 1513 insertions(+), 1096 deletions(-) diff --git a/.gitmodules b/.gitmodules index 85c12576..b6984f0f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,7 +20,7 @@ [submodule "ncar-physics"] path = src/physics/ncar_ccpp url = https://github.com/ESCOMP/atmospheric_physics - fxtag = 045b630a8c3b41d90b6c006392c3907af762dd39 + fxtag = d46bb55e233e8f16b4e7a7b5a90352e99c7a5d72 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics [submodule "ccs_config"] diff --git a/cime_config/cam_autogen.py b/cime_config/cam_autogen.py index 3d5ed312..e08b1f5b 100644 --- a/cime_config/cam_autogen.py +++ b/cime_config/cam_autogen.py @@ -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 = retvals + retcode, reg_file_list, ic_names, registry_constituents = retvals # Raise error if gen_registry failed: if retcode != 0: emsg = "ERROR:Unable to generate CAM data structures from {}, err = {}" @@ -406,14 +406,15 @@ 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) + reg_file_paths, ic_names, registry_constituents) 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() # End if - return genreg_dir, do_gen_registry, reg_file_paths, ic_names + return genreg_dir, do_gen_registry, reg_file_paths, ic_names, registry_constituents ############################################################################### def generate_physics_suites(build_cache, preproc_defs, host_name, @@ -443,7 +444,8 @@ def generate_physics_suites(build_cache, preproc_defs, host_name, suite_search = [source_mods_dir, atm_suites_path, atm_test_suites_path] # Find all scheme metadata files, organized by scheme name atm_schemes_path = os.path.join(atm_phys_top_dir, "schemes") - source_search = [source_mods_dir, atm_schemes_path] + atm_test_schemes_path = os.path.join(atm_phys_top_dir, "test", "test_schemes") + source_search = [source_mods_dir, atm_schemes_path, atm_test_schemes_path] all_scheme_files = _find_metadata_files(source_search, find_scheme_names) # Find the SDFs specified for this model build @@ -657,7 +659,7 @@ 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): + cap_database, ic_names, registry_constituents): ############################################################################### """ Generate the host model initialization source code files @@ -695,8 +697,8 @@ 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, init_dir, - _find_file, source_paths, + retmsg = write_init_files(cap_database, ic_names, registry_constituents, + init_dir, _find_file, source_paths, gen_fort_indent, _LOGGER) #Check that script ran properly: diff --git a/cime_config/cam_build_cache.py b/cime_config/cam_build_cache.py index 2bda072e..70b31853 100644 --- a/cime_config/cam_build_cache.py +++ b/cime_config/cam_build_cache.py @@ -226,6 +226,7 @@ def __init__(self, build_cache): self.__kind_types = {} self.__reg_gen_files = [] self.__ic_names = {} + self.__constituents = [] if os.path.exists(build_cache): # Initialize build cache state _, cache = read_xml_file(build_cache) @@ -252,6 +253,10 @@ def __init__(self, build_cache): # end if itext = clean_xml_text(item) self.__ic_names[stdname].append(itext) + elif item.tag == 'constituent_entry': + stdname = item.get('standard_name') + itext = clean_xml_text(item) + self.__constituents.append(itext) else: emsg = "ERROR: Unknown registry tag, '{}'" raise ValueError(emsg.format(item.tag)) @@ -313,7 +318,7 @@ def __init__(self, build_cache): # end if def update_registry(self, gen_reg_file, registry_source_files, - dycore, reg_file_list, ic_names): + dycore, reg_file_list, ic_names, constituents): """Replace the registry cache data with input data """ self.__dycore = dycore @@ -328,6 +333,7 @@ def update_registry(self, gen_reg_file, registry_source_files, # ic_names are the initial condition variable names from the registry, # and should already be of type dict: self.__ic_names = ic_names + self.__constituents = constituents def update_ccpp(self, suite_definition_files, scheme_files, host_files, xml_files, namelist_meta_files, namelist_groups, @@ -400,6 +406,10 @@ def write(self): ic_entry.text = ic_name # end for # end for + for stdname in self.__constituents: + const_entry = ET.SubElement(registry, 'constituent_entry') + const_entry.text = stdname + # end for # CCPP ccpp = ET.SubElement(new_cache, 'CCPP') for sfile in self.__sdfs.values(): @@ -603,5 +613,9 @@ def ic_names(self): """Return a copy of the registry initial conditions dictionary""" return dict(self.__ic_names) + def constituents(self): + """Return a copy of the registry constituents list""" + return list(self.__constituents) + ############# # End of file diff --git a/cime_config/cam_config.py b/cime_config/cam_config.py index 80bef16e..afb298a9 100644 --- a/cime_config/cam_config.py +++ b/cime_config/cam_config.py @@ -838,7 +838,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 = retvals + reg_dir, force_ccpp, reg_files, ic_names, registry_constituents = retvals #Add registry path to config object: reg_dir_desc = "Location of auto-generated registry code." @@ -871,7 +871,7 @@ 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) + capgen_db, ic_names, registry_constituents) #Add registry path to config object: init_dir_desc = "Location of auto-generated physics initialization code." diff --git a/src/data/air_composition.F90 b/src/data/air_composition.F90 index f202ae97..e84fc837 100644 --- a/src/data/air_composition.F90 +++ b/src/data/air_composition.F90 @@ -346,8 +346,8 @@ subroutine air_composition_init() ! ! CLDICE ! - case('cloud_ice_water_mixing_ratio_wrt_moist_air_and_condensed_water') - call air_species_info('cloud_ice_water_mixing_ratio_wrt_moist_air_and_condensed_water', & + case('cloud_ice_mixing_ratio_wrt_moist_air_and_condensed_water') + call air_species_info('cloud_ice_mixing_ratio_wrt_moist_air_and_condensed_water', & ix, mw) thermodynamic_active_species_idx(icnst) = ix thermodynamic_active_species_cp (icnst) = cpice @@ -408,7 +408,7 @@ subroutine air_composition_init() ! ! GRAUQM ! - case('graupel_water_mixing_ratio_wrt_moist_air_and_conedensed_water') + case('graupel_water_mixing_ratio_wrt_moist_air_and_condensed_water') call air_species_info('graupel_water_mixing_ratio_wrt_moist_air_and_condensed_water', & ix, mw) thermodynamic_active_species_idx(icnst) = ix diff --git a/src/data/generate_registry_data.py b/src/data/generate_registry_data.py index 0b212a9f..e3d5abf9 100755 --- a/src/data/generate_registry_data.py +++ b/src/data/generate_registry_data.py @@ -1734,6 +1734,31 @@ def _create_ic_name_dict(registry): # end for return ic_name_dict +############################################################################### +def _create_constituent_list(registry): +############################################################################### + """ + Create a list of all constituents found in the registry. + To be used by write_init_files.py - need to keep track + of all constituent variables, not just ones required by + CCPP metadata, to handle runtime constituents + """ + constituent_list = [] + for section in registry: + if section.tag == 'file': + for obj in section: + if obj.tag == 'variable': + if obj.get('constituent'): + stdname = obj.get('standard_name') + constituent_list.append(stdname) + # end if (ignore non-constituents) + # end if (ignore other node types) + # end for + # end if (ignore other node types) + # end for + return constituent_list + + ############################################################################### def gen_registry(registry_file, dycore, outdir, indent, src_mod, src_root, loglevel=None, logger=None, @@ -1794,6 +1819,7 @@ def gen_registry(registry_file, dycore, outdir, indent, retcode = 1 files = None ic_names = None + constituents = None else: library_name = registry.get('name') emsg = f"Parsing registry, {library_name}" @@ -1803,9 +1829,10 @@ def gen_registry(registry_file, dycore, outdir, indent, src_root, reg_dir, indent, logger) # See comment in _create_ic_name_dict ic_names = _create_ic_name_dict(registry) + registry_constituents = _create_constituent_list(registry) retcode = 0 # Throw exception on error # end if - return retcode, files, ic_names + return retcode, files, ic_names, registry_constituents def main(): """Function to execute when module called as a script""" diff --git a/src/data/registry.xml b/src/data/registry.xml index 4b54088a..4a199b9f 100644 --- a/src/data/registry.xml +++ b/src/data/registry.xml @@ -445,5 +445,17 @@ horizontal_dimension vertical_layer_dimension RAINQM cnst_RAINQM + + snow mass mixing ratio with respect to moist air plus all airborne condensates + SNOWQM cnst_SNOWQM + + + graupel mass mixing ratio with respect to moist air plus all airborne condensates + GRAUQM cnst_GRAUQM + diff --git a/src/data/write_init_files.py b/src/data/write_init_files.py index 03e0bd93..b0f92d1c 100644 --- a/src/data/write_init_files.py +++ b/src/data/write_init_files.py @@ -47,7 +47,7 @@ #Main function ############## -def write_init_files(cap_database, ic_names, outdir, +def write_init_files(cap_database, ic_names, registry_constituents, outdir, file_find_func, source_paths, indent, logger, phys_check_filename=None, phys_input_filename=None): @@ -131,7 +131,7 @@ def write_init_files(cap_database, ic_names, outdir, # Gather all the host model variables that are required by # any of the compiled CCPP physics suites. - host_vars, constituent_set, retmsg = gather_ccpp_req_vars(cap_database) + host_vars, constituent_set, retmsg = gather_ccpp_req_vars(cap_database, registry_constituents) # Quit now if there are missing variables if retmsg: @@ -174,12 +174,12 @@ def write_init_files(cap_database, ic_names, outdir, # end for # Write public parameters: - retvals = write_ic_params(outfile, host_vars, ic_names) + retvals = write_ic_params(outfile, host_vars, ic_names, registry_constituents) ic_names, ic_max_len, stdname_max_len = retvals # Write initial condition arrays: write_ic_arrays(outfile, ic_names, ic_max_len, - stdname_max_len, host_vars) + stdname_max_len, host_vars, registry_constituents) # Add "contains" statement: outfile.end_module_header() @@ -299,7 +299,7 @@ def _find_and_add_host_variable(stdname, host_dict, var_dict): return missing_vars ############################################################################## -def gather_ccpp_req_vars(cap_database): +def gather_ccpp_req_vars(cap_database, registry_constituents): """ Generate a list of host-model and constituent variables required by the CCPP physics suites potentially being used @@ -332,13 +332,12 @@ def gather_ccpp_req_vars(cap_database): (stdname not in req_vars) and (stdname not in _EXCLUDED_STDNAMES)): if is_const: - #Variable is a constituent, so may not be known - #until runtime, but still need variable names in order - #to read from a file if need be: - req_vars[stdname] = cvar - #Add variable to constituent set: constituent_vars.add(stdname) + #Add variable to required variable list if it's not a registry constituent + if stdname not in registry_constituents: + req_vars[stdname] = cvar + # end if else: # We need to work with the host model version of this variable missing = _find_and_add_host_variable(stdname, host_dict, @@ -360,7 +359,7 @@ def gather_ccpp_req_vars(cap_database): #FORTRAN WRITING FUNCTIONS ########################## -def write_ic_params(outfile, host_vars, ic_names): +def write_ic_params(outfile, host_vars, ic_names, registry_constituents): """ Write public parameter declarations needed @@ -371,7 +370,7 @@ def write_ic_params(outfile, host_vars, ic_names): #Create new Fortran integer parameter to store total number of variables: outfile.comment("Total number of physics-related variables:", 1) - num_pvars = len(host_vars) + num_pvars = len(host_vars) + len(registry_constituents) outfile.write(f"integer, public, parameter :: phys_var_num = {num_pvars}", 1) num_cvars = len(_EXCLUDED_STDNAMES) @@ -420,7 +419,7 @@ def write_ic_params(outfile, host_vars, ic_names): ###### def write_ic_arrays(outfile, ic_name_dict, ic_max_len, - stdname_max_len, host_vars): + stdname_max_len, host_vars, registry_constituents): """ Write initial condition arrays to store @@ -429,7 +428,7 @@ def write_ic_arrays(outfile, ic_name_dict, ic_max_len, """ #Create variable name array string lists: - num_input_vars = len(host_vars) + num_input_vars = len(host_vars) + len(registry_constituents) stdname_strs = [] ic_name_strs = [] @@ -446,6 +445,10 @@ def write_ic_arrays(outfile, ic_name_dict, ic_max_len, # for each variable with the proper length, : for hvar in host_vars: var_stdname = hvar.get_prop_value('standard_name') + if var_stdname in registry_constituents: + # skip registry constituents; we'll tackle these after + continue + # end if # Create standard_name string with proper size, and append to list: stdname_strs.append(f"'{var_stdname: <{stdname_max_len}}'") @@ -466,6 +469,26 @@ def write_ic_arrays(outfile, ic_name_dict, ic_max_len, ic_name_strs.append(', '.join(f"'{n}'" for n in ic_names_with_spaces)) # end for + # Add any constituent variables: + for const in registry_constituents: + stdname_strs.append(f"'{const: <{stdname_max_len}}'") + + #Extract input (IC) names list: + ic_names = ic_name_dict[const] + + # Determine number of IC names for variable: + ic_name_num = len(ic_names) + + #Pad the ic_names to ic_max_len: + ic_names_with_spaces = [f"{x: <{ic_max_len}}" for x in ic_names] + if ic_name_num < max_ic_num: + ic_names_with_spaces.extend(fake_ic_names[:-ic_name_num]) + # end if + + #Append new ic_names to string list: + ic_name_strs.append(', '.join(f"'{n}'" for n in ic_names_with_spaces)) + # end if + #Write arrays to Fortran file: #---------------------------- @@ -551,6 +574,18 @@ def write_ic_arrays(outfile, ic_name_dict, ic_max_len, #Write line to file: outfile.write(log_arr_str, 2) # end for + arr_suffix = ', &' + for var_num, var_name in enumerate(registry_constituents): + # If at the end of the list, then update suffix: + if var_num == num_input_vars-len(host_vars)-1: + arr_suffix = ' /)' + # end if + #Set array values: + log_arr_str = '.false.' + arr_suffix + + #Write line to file: + outfile.write(log_arr_str, 2) + # end for outfile.blank_line() @@ -566,7 +601,6 @@ def write_ic_arrays(outfile, ic_name_dict, ic_max_len, #variable is a parameter: arr_suffix = ', &' for var_num, hvar in enumerate(host_vars): - var_stdname = hvar.get_prop_value('standard_name') #If at the end of the list, then update suffix: if var_num == num_input_vars-1: arr_suffix = ' /)' @@ -580,6 +614,17 @@ def write_ic_arrays(outfile, ic_name_dict, ic_max_len, #Write line to file: outfile.write(log_arr_str, 2) # end for + arr_suffix = ', &' + for var_num, varname in enumerate(registry_constituents): + #If at the end of the list, then update suffix: + if var_num == num_input_vars-len(host_vars)-1: + arr_suffix = ' /)' + # end if + #Set array values: + log_arr_str = 'UNINITIALIZED' + arr_suffix + #Write line to file: + outfile.write(log_arr_str, 2) + # end for outfile.blank_line() #---------------------------- @@ -842,10 +887,13 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports, ["physics_data", ["read_field", "find_input_name_idx", "no_exist_idx", "init_mark_idx", "prot_no_init_idx", "const_idx"]], - ["cam_ccpp_cap", ["ccpp_physics_suite_variables", "cam_constituents_array", "cam_model_const_properties"]], + ["cam_ccpp_cap", ["ccpp_physics_suite_variables", + "cam_constituents_array", + "cam_model_const_properties"]], ["ccpp_kinds", ["kind_phys"]], [phys_check_fname_str, ["phys_var_num", "phys_var_stdnames", - "input_var_names", "std_name_len"]], + "input_var_names", "std_name_len", + "is_initialized"]], ["ccpp_constituent_prop_mod", ["ccpp_constituent_prop_ptr_t"]], ["cam_logfile", ["iulog"]]] @@ -888,10 +936,12 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports, outfile.write("character(len=2) :: sep3 !String separator used to print err messages", 2) outfile.write("real(kind=kind_phys), pointer :: field_data_ptr(:,:,:)", 2) outfile.write("logical :: var_found !Bool to determine if consituent found in data files", 2) + outfile.write("character(len=std_name_len) :: std_name !Variable to hold constiutent standard name", 2) outfile.blank_line() outfile.comment("Fields needed for getting default data value for constituents", 2) outfile.write("type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:)", 2) outfile.write("real(kind=kind_phys) :: constituent_default_value", 2) + outfile.write("real(kind=kind_phys) :: constituent_min_value", 2) outfile.write("integer :: constituent_errflg", 2) outfile.write("character(len=512) :: constituent_errmsg", 2) outfile.write("logical :: constituent_has_default", 2) @@ -982,48 +1032,7 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports, # Handle the case where the required variable is a constituent outfile.write("case (const_idx)", 5) outfile.blank_line() - outfile.comment("If an index was found in the constituent hash table, then read in the data to that index of the constituent array", 6) - outfile.blank_line() - outfile.write("var_found = .false.", 6) - outfile.write("field_data_ptr => cam_constituents_array()", 6) - outfile.blank_line() - outfile.comment("Check if constituent standard name in registered SIMA standard names list:", 6) - outfile.write("if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then", 6) - outfile.comment("Find array index to extract correct input names:", 7) - outfile.write("do n=1, phys_var_num", 7) - outfile.write("if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then", 8) - outfile.write("const_input_idx = n", 9) - outfile.write("exit", 9) - outfile.write("end if", 8) - outfile.write("end do", 7) - outfile.write("call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found)", 7) - outfile.write("else", 6) - outfile.comment("If not in standard names list, then just use constituent name as input file name:",7) - outfile.write("call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found)", 7) - outfile.write("end if", 6) - outfile.write("if(.not. var_found) then", 6) - outfile.write("const_props => cam_model_const_properties()", 7) - outfile.write("constituent_has_default = .false.", 7) - outfile.write("call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg)", 7) - outfile.write("if (constituent_errflg /= 0) then", 7) - outfile.write("call endrun(constituent_errmsg, file=__FILE__, line=__LINE__)", 8) - outfile.write("end if", 7) - outfile.write("if (constituent_has_default) then", 7) - outfile.write("call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg)", 8) - outfile.write("if (constituent_errflg /= 0) then", 8) - outfile.write("call endrun(constituent_errmsg, file=__FILE__, line=__LINE__)", 9) - outfile.write("end if", 8) - outfile.write("field_data_ptr(:,:,constituent_idx) = constituent_default_value", 8) - outfile.write("if (masterproc) then", 8) - outfile.write("write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', constituent_default_value", 9) - outfile.write("end if", 8) - outfile.write("else", 7) - outfile.write("field_data_ptr(:,:,constituent_idx) = 0._kind_phys", 8) - outfile.write("if (masterproc) then", 8) - outfile.write("write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.'", 9) - outfile.write("end if", 8) - outfile.write("end if", 7) - outfile.write("end if", 6) + outfile.comment("If an index was found in the constituent hash table, then do nothing, this will be handled later", 6) outfile.blank_line() # start default case steps: @@ -1073,6 +1082,62 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports, # End suite loop: outfile.write(" end do !CCPP suites", 2) outfile.blank_line() + + # Read in constituent data + outfile.comment("Read in constituent variables if not using init variables", 2) + outfile.write("field_data_ptr => cam_constituents_array()", 2) + outfile.write("const_props => cam_model_const_properties()", 2) + outfile.blank_line() + outfile.comment("Iterate over all registered constituents", 2) + outfile.write("do constituent_idx = 1, size(const_props)", 2) + outfile.write("var_found = .false.", 3) + outfile.comment("Check if constituent standard name in registered SIMA standard names list:", 3) + outfile.write("call const_props(constituent_idx)%standard_name(std_name)", 3) + outfile.write("if(any(phys_var_stdnames == trim(std_name))) then", 3) + outfile.comment("Don't read the variable in if it's already initialized", 4) + outfile.write("if (is_initialized(std_name)) then", 4) + outfile.write("cycle", 5) + outfile.write("end if", 4) + outfile.comment("Find array index to extract correct input names:", 4) + outfile.write("do n=1, phys_var_num", 4) + outfile.write("if(trim(phys_var_stdnames(n)) == trim(std_name)) then", 5) + outfile.write("const_input_idx = n", 6) + outfile.write("exit", 6) + outfile.write("end if", 5) + outfile.write("end do", 4) + outfile.write("call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found)", 4) + outfile.write("else", 3) + outfile.comment("If not in standard names list, then just use constituent name as input file name:",4) + outfile.write("call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found)", 4) + outfile.write("end if", 3) + outfile.write("if(.not. var_found) then", 3) + outfile.write("constituent_has_default = .false.", 4) + outfile.write("call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg)", 4) + outfile.write("if (constituent_errflg /= 0) then", 4) + outfile.write("call endrun(constituent_errmsg, file=__FILE__, line=__LINE__)", 5) + outfile.write("end if", 4) + outfile.write("if (constituent_has_default) then", 4) + outfile.write("call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg)", 5) + outfile.write("if (constituent_errflg /= 0) then", 5) + outfile.write("call endrun(constituent_errmsg, file=__FILE__, line=__LINE__)", 6) + outfile.write("end if", 5) + outfile.write("field_data_ptr(:,:,constituent_idx) = constituent_default_value", 5) + outfile.write("if (masterproc) then", 5) + outfile.write("write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value", 6) + outfile.write("end if", 5) + outfile.write("else", 4) + outfile.comment("Intialize to constituent's configured minimum value", 5) + outfile.write("call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg)", 5) + outfile.write("field_data_ptr(:,:,constituent_idx) = constituent_min_value", 5) + outfile.write("if (masterproc) then", 5) + outfile.write("write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.'", 6) + outfile.write("end if", 5) + outfile.write("end if", 4) + outfile.write("end if", 3) + outfile.write("end do", 2) + outfile.blank_line() + + # start default case steps: # End subroutine: outfile.write("end subroutine physics_read_data", 1) @@ -1150,7 +1215,9 @@ def write_phys_check_subroutine(outfile, host_dict, host_vars, host_imports, ["physics_data", ["check_field", "find_input_name_idx", "no_exist_idx", "init_mark_idx", "prot_no_init_idx", "const_idx"]], - ["cam_ccpp_cap", ["ccpp_physics_suite_variables", "cam_advected_constituents_array"]], + ["cam_ccpp_cap", ["ccpp_physics_suite_variables", + "cam_advected_constituents_array", + "cam_model_const_properties"]], ["cam_constituents", ["const_get_index"]], ["ccpp_kinds", ["kind_phys"]], ["cam_logfile", ["iulog"]], @@ -1158,6 +1225,7 @@ def write_phys_check_subroutine(outfile, host_dict, host_vars, host_imports, ["phys_vars_init_check", ["is_read_from_file"]], ["ioFileMod", ["cam_get_file"]], ["cam_pio_utils", ["cam_pio_openfile", "cam_pio_closefile"]], + ["ccpp_constituent_prop_mod", ["ccpp_constituent_prop_ptr_t"]], [phys_check_fname_str, ["phys_var_num", "phys_var_stdnames", "input_var_names", @@ -1205,7 +1273,9 @@ def write_phys_check_subroutine(outfile, host_dict, host_vars, host_imports, outfile.write("logical :: file_found", 2) outfile.write("logical :: is_first", 2) outfile.write("logical :: is_read", 2) + outfile.write("character(len=std_name_len) :: std_name !Variable to hold constiutent standard name", 2) outfile.write("real(kind=kind_phys), pointer :: field_data_ptr(:,:,:)", 2) + outfile.write("type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:)", 2) outfile.blank_line() # Initialize variables: @@ -1269,24 +1339,7 @@ def write_phys_check_subroutine(outfile, host_dict, host_vars, host_imports, outfile.comment("First check if the required variable is a constituent:", 4) outfile.write("call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.)", 4) outfile.write("if (constituent_idx > -1) then", 4) - outfile.comment("The required variable is a constituent. Call check variable routine on the relevant index of the constituent array", 5) - outfile.write("field_data_ptr => cam_advected_constituents_array()", 5) - outfile.blank_line() - outfile.comment("Check if constituent standard name in registered SIMA standard names list:", 5) - outfile.write("if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then", 5) - outfile.comment("Find array index to extract correct input names:", 6) - outfile.write("do n=1, phys_var_num", 6) - outfile.write("if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then", 7) - outfile.write("const_input_idx = n", 8) - outfile.write("exit", 8) - outfile.write("end if", 7) - outfile.write("end do", 6) - outfile.write("call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), ccpp_required_data(req_idx), min_difference, min_relative_value, is_first)", 6) - outfile.write("else", 5) - outfile.comment("If not in standard names list, then just use constituent name as input file name:",6) - outfile.write("call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), ccpp_required_data(req_idx), min_difference, min_relative_value, is_first)", 6) - outfile.write("end if", 5) - + outfile.write("cycle", 5) outfile.write("else", 4) outfile.comment("The required variable is not a constituent. Check if the variable was read from a file", 5) @@ -1322,6 +1375,27 @@ def write_phys_check_subroutine(outfile, host_dict, host_vars, host_imports, # End suite loop: outfile.write("end do !CCPP suites", 2) outfile.blank_line() + outfile.comment("Check constituent variables", 2) + outfile.write("field_data_ptr => cam_advected_constituents_array()", 2) + outfile.write("const_props => cam_model_const_properties()", 2) + outfile.blank_line() + outfile.write("do constituent_idx = 1, size(const_props)", 2) + outfile.comment("Check if constituent standard name in registered SIMA standard names list:", 3) + outfile.write("call const_props(constituent_idx)%standard_name(std_name)", 3) + outfile.write("if(any(phys_var_stdnames == std_name)) then", 3) + outfile.comment("Find array index to extract correct input names:", 4) + outfile.write("do n=1, phys_var_num", 4) + outfile.write("if(trim(phys_var_stdnames(n)) == trim(std_name)) then", 5) + outfile.write("const_input_idx = n", 6) + outfile.write("exit", 6) + outfile.write("end if", 5) + outfile.write("end do", 4) + outfile.write("call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, is_first)", 4) + outfile.write("else", 3) + outfile.comment("If not in standard names list, then just use constituent name as input file name:",4) + outfile.write("call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, is_first)", 4) + outfile.write("end if", 3) + outfile.write("end do", 2) # Close check file outfile.comment("Close check file:", 2) diff --git a/src/physics/ncar_ccpp b/src/physics/ncar_ccpp index 045b630a..29c7663a 160000 --- a/src/physics/ncar_ccpp +++ b/src/physics/ncar_ccpp @@ -1 +1 @@ -Subproject commit 045b630a8c3b41d90b6c006392c3907af762dd39 +Subproject commit 29c7663a68d9b66bfe7926a56a595dbcbf2c385c diff --git a/test/unit/sample_files/build_cache_files/update_reg_build_cache.xml b/test/unit/sample_files/build_cache_files/update_reg_build_cache.xml index e773ee2c..5a4273b9 100644 --- a/test/unit/sample_files/build_cache_files/update_reg_build_cache.xml +++ b/test/unit/sample_files/build_cache_files/update_reg_build_cache.xml @@ -8,6 +8,8 @@ tmp/cam_build_cache/test_reg.xml heart brain + cnst_1 + cnst_2 diff --git a/test/unit/sample_files/write_init_files/phys_vars_init_check_cnst.F90 b/test/unit/sample_files/write_init_files/phys_vars_init_check_cnst.F90 index 6849ef70..ceee4cb2 100644 --- a/test/unit/sample_files/write_init_files/phys_vars_init_check_cnst.F90 +++ b/test/unit/sample_files/write_init_files/phys_vars_init_check_cnst.F90 @@ -40,7 +40,7 @@ module phys_vars_init_check_cnst integer, public, parameter :: std_name_len = 25 ! Max length of input (IC) file variable names: - integer, public, parameter :: ic_name_len = 13 + integer, public, parameter :: ic_name_len = 12 ! Physics-related input variable standard names: character(len=25), public, protected :: phys_var_stdnames(phys_var_num) = (/ & @@ -66,10 +66,10 @@ module phys_vars_init_check_cnst "suite_name ", & "suite_part " /) !Array storing all registered IC file input names for each variable: - character(len=13), public, protected :: input_var_names(2, phys_var_num) = reshape((/ & - 'theta ', 'pot_temp ', & - 'slp ', 'sea_lev_pres ', & - 'COOL_CAT ', 'cnst_COOL_CAT' /), (/2, phys_var_num/)) + character(len=12), public, protected :: input_var_names(2, phys_var_num) = reshape((/ & + 'theta ', 'pot_temp ', & + 'slp ', 'sea_lev_pres', & + 'COOL_CAT ', 'cnst_COOL_CAT' /), (/2, phys_var_num/)) ! Array indicating whether or not variable is protected: logical, public, protected :: protected_vars(phys_var_num)= (/ & diff --git a/test/unit/sample_files/write_init_files/physics_inputs_4D.F90 b/test/unit/sample_files/write_init_files/physics_inputs_4D.F90 index 75efc762..250179c8 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_4D.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_4D.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_4D, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_4D, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_4D, only: slp, theta @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -212,23 +170,78 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) - use pio, only: file_desc_t, pio_nowrite - use cam_abortutils, only: endrun - use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX - use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array - use cam_constituents, only: const_get_index - use ccpp_kinds, only: kind_phys - use cam_logfile, only: iulog - use spmd_utils, only: masterproc - use phys_vars_init_check, only: is_read_from_file - use ioFileMod, only: cam_get_file - use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile - use phys_vars_init_check_4D, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len - use physics_types_4D, only: slp, theta + use pio, only: file_desc_t, pio_nowrite + use cam_abortutils, only: endrun + use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX + use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties + use cam_constituents, only: const_get_index + use ccpp_kinds, only: kind_phys + use cam_logfile, only: iulog + use spmd_utils, only: masterproc + use phys_vars_init_check, only: is_read_from_file + use ioFileMod, only: cam_get_file + use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t + use phys_vars_init_check_4D, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use physics_types_4D, only: slp, theta ! Dummy arguments character(len=SHR_KIND_CL), intent(in) :: file_name @@ -260,7 +273,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -299,25 +314,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -344,6 +341,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_bvd.F90 b/test/unit/sample_files/write_init_files/physics_inputs_bvd.F90 index 46cc2b53..99fa3c3d 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_bvd.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_bvd.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_bvd, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_bvd, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_bad_vertdim, only: slp, theta @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -212,6 +170,60 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) @@ -219,7 +231,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use cam_abortutils, only: endrun use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys use cam_logfile, only: iulog @@ -227,6 +239,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use phys_vars_init_check, only: is_read_from_file use ioFileMod, only: cam_get_file use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use phys_vars_init_check_bvd, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len use physics_types_bad_vertdim, only: slp, theta @@ -260,7 +273,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -299,25 +314,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -344,6 +341,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_cnst.F90 b/test/unit/sample_files/write_init_files/physics_inputs_cnst.F90 index 2289adfd..218d7f48 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_cnst.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_cnst.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_cnst, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_cnst, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_simple, only: slp, theta @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -212,6 +170,60 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) @@ -219,7 +231,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use cam_abortutils, only: endrun use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys use cam_logfile, only: iulog @@ -227,6 +239,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use phys_vars_init_check, only: is_read_from_file use ioFileMod, only: cam_get_file use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use phys_vars_init_check_cnst, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len use physics_types_simple, only: slp, theta @@ -260,7 +273,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -299,25 +314,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -345,6 +342,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_ddt.F90 b/test/unit/sample_files/write_init_files/physics_inputs_ddt.F90 index de9adfea..d5675487 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_ddt.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_ddt.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_ddt, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_ddt, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_ddt, only: phys_state, slp @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -212,23 +170,78 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) - use pio, only: file_desc_t, pio_nowrite - use cam_abortutils, only: endrun - use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX - use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array - use cam_constituents, only: const_get_index - use ccpp_kinds, only: kind_phys - use cam_logfile, only: iulog - use spmd_utils, only: masterproc - use phys_vars_init_check, only: is_read_from_file - use ioFileMod, only: cam_get_file - use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile - use phys_vars_init_check_ddt, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len - use physics_types_ddt, only: phys_state, slp + use pio, only: file_desc_t, pio_nowrite + use cam_abortutils, only: endrun + use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX + use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties + use cam_constituents, only: const_get_index + use ccpp_kinds, only: kind_phys + use cam_logfile, only: iulog + use spmd_utils, only: masterproc + use phys_vars_init_check, only: is_read_from_file + use ioFileMod, only: cam_get_file + use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t + use phys_vars_init_check_ddt, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use physics_types_ddt, only: phys_state, slp ! Dummy arguments character(len=SHR_KIND_CL), intent(in) :: file_name @@ -260,7 +273,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -299,25 +314,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -345,6 +342,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_ddt2.F90 b/test/unit/sample_files/write_init_files/physics_inputs_ddt2.F90 index 2dc7d3b9..57ea3c19 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_ddt2.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_ddt2.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_ddt2, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_ddt2, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_ddt2, only: phys_state @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -212,6 +170,60 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) @@ -219,7 +231,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use cam_abortutils, only: endrun use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys use cam_logfile, only: iulog @@ -227,6 +239,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use phys_vars_init_check, only: is_read_from_file use ioFileMod, only: cam_get_file use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use phys_vars_init_check_ddt2, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len use physics_types_ddt2, only: phys_state @@ -260,7 +273,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -299,25 +314,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -345,6 +342,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_ddt_array.F90 b/test/unit/sample_files/write_init_files/physics_inputs_ddt_array.F90 index 620eceed..c9c0b278 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_ddt_array.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_ddt_array.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_ddt_array, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_ddt_array, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_ddt_array, only: ix_theta, phys_state @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -212,6 +170,60 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) @@ -219,7 +231,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use cam_abortutils, only: endrun use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys use cam_logfile, only: iulog @@ -227,6 +239,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use phys_vars_init_check, only: is_read_from_file use ioFileMod, only: cam_get_file use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use phys_vars_init_check_ddt_array, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len use physics_types_ddt_array, only: ix_theta, phys_state @@ -260,7 +273,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -299,25 +314,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -345,6 +342,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_host_var.F90 b/test/unit/sample_files/write_init_files/physics_inputs_host_var.F90 index 34d18e84..9b4dc702 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_host_var.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_host_var.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_host_var, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_host_var, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_host_var, only: slp @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -209,6 +167,60 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) @@ -216,7 +228,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use cam_abortutils, only: endrun use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys use cam_logfile, only: iulog @@ -224,6 +236,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use phys_vars_init_check, only: is_read_from_file use ioFileMod, only: cam_get_file use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use phys_vars_init_check_host_var, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len use physics_types_host_var, only: slp @@ -257,7 +270,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -296,25 +311,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -338,6 +335,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_mf.F90 b/test/unit/sample_files/write_init_files/physics_inputs_mf.F90 index 868c512b..7ccaf7ee 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_mf.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_mf.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_mf, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_mf, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use ref_theta, only: theta @@ -70,10 +70,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -134,51 +136,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -213,24 +171,79 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) - use pio, only: file_desc_t, pio_nowrite - use cam_abortutils, only: endrun - use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX - use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array - use cam_constituents, only: const_get_index - use ccpp_kinds, only: kind_phys - use cam_logfile, only: iulog - use spmd_utils, only: masterproc - use phys_vars_init_check, only: is_read_from_file - use ioFileMod, only: cam_get_file - use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile - use phys_vars_init_check_mf, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len - use ref_theta, only: theta - use physics_types_mf, only: slp + use pio, only: file_desc_t, pio_nowrite + use cam_abortutils, only: endrun + use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX + use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties + use cam_constituents, only: const_get_index + use ccpp_kinds, only: kind_phys + use cam_logfile, only: iulog + use spmd_utils, only: masterproc + use phys_vars_init_check, only: is_read_from_file + use ioFileMod, only: cam_get_file + use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t + use phys_vars_init_check_mf, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use ref_theta, only: theta + use physics_types_mf, only: slp ! Dummy arguments character(len=SHR_KIND_CL), intent(in) :: file_name @@ -262,7 +275,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -301,25 +316,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -347,6 +344,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_no_horiz.F90 b/test/unit/sample_files/write_init_files/physics_inputs_no_horiz.F90 index 96453a7f..d238768e 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_no_horiz.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_no_horiz.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_no_horiz, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_no_horiz, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_no_horiz, only: slp, theta @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -212,6 +170,60 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) @@ -219,7 +231,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use cam_abortutils, only: endrun use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys use cam_logfile, only: iulog @@ -227,6 +239,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use phys_vars_init_check, only: is_read_from_file use ioFileMod, only: cam_get_file use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use phys_vars_init_check_no_horiz, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len use physics_types_no_horiz, only: slp, theta @@ -260,7 +273,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -299,25 +314,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -344,6 +341,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_noreq.F90 b/test/unit/sample_files/write_init_files/physics_inputs_noreq.F90 index 2d532a63..52eb8cf9 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_noreq.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_noreq.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_noreq, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_noreq, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog @@ -68,10 +68,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -132,51 +134,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -205,6 +163,60 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) @@ -212,7 +224,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use cam_abortutils, only: endrun use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys use cam_logfile, only: iulog @@ -220,6 +232,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use phys_vars_init_check, only: is_read_from_file use ioFileMod, only: cam_get_file use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use phys_vars_init_check_noreq, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len ! Dummy arguments @@ -252,7 +265,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -291,25 +306,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -329,6 +326,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_param.F90 b/test/unit/sample_files/write_init_files/physics_inputs_param.F90 index 0136b24c..3cdfb21a 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_param.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_param.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_param, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_param, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_param, only: g, slp, theta @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -215,6 +173,60 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) @@ -222,7 +234,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use cam_abortutils, only: endrun use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys use cam_logfile, only: iulog @@ -230,6 +242,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use phys_vars_init_check, only: is_read_from_file use ioFileMod, only: cam_get_file use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use phys_vars_init_check_param, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len use physics_types_param, only: g, slp, theta @@ -263,7 +276,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -302,25 +317,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -351,6 +348,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_protect.F90 b/test/unit/sample_files/write_init_files/physics_inputs_protect.F90 index b5c6e5f4..c578c2fc 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_protect.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_protect.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_protect, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_protect, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_protected, only: slp, theta @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -212,6 +170,60 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) @@ -219,7 +231,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use cam_abortutils, only: endrun use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys use cam_logfile, only: iulog @@ -227,6 +239,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use phys_vars_init_check, only: is_read_from_file use ioFileMod, only: cam_get_file use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use phys_vars_init_check_protect, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len use physics_types_protected, only: slp, theta @@ -260,7 +273,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -299,25 +314,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -345,6 +342,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_scalar.F90 b/test/unit/sample_files/write_init_files/physics_inputs_scalar.F90 index 065fb36f..4159f127 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_scalar.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_scalar.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_scalar, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_scalar, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_scalar_var, only: slp, theta @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -212,6 +170,60 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) @@ -219,7 +231,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use cam_abortutils, only: endrun use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys use cam_logfile, only: iulog @@ -227,6 +239,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use phys_vars_init_check, only: is_read_from_file use ioFileMod, only: cam_get_file use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use phys_vars_init_check_scalar, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len use physics_types_scalar_var, only: slp, theta @@ -260,7 +273,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -299,25 +314,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -344,6 +341,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/sample_files/write_init_files/physics_inputs_simple.F90 b/test/unit/sample_files/write_init_files/physics_inputs_simple.F90 index f4eb298c..1b55d8a3 100644 --- a/test/unit/sample_files/write_init_files/physics_inputs_simple.F90 +++ b/test/unit/sample_files/write_init_files/physics_inputs_simple.F90 @@ -36,7 +36,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys - use phys_vars_init_check_simple, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len + use phys_vars_init_check_simple, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len, is_initialized use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use cam_logfile, only: iulog use physics_types_simple, only: slp, theta @@ -69,10 +69,12 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia character(len=2) :: sep3 !String separator used to print err messages real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) logical :: var_found !Bool to determine if consituent found in data files + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name ! Fields needed for getting default data value for constituents type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) real(kind=kind_phys) :: constituent_default_value + real(kind=kind_phys) :: constituent_min_value integer :: constituent_errflg character(len=512) :: constituent_errmsg logical :: constituent_has_default @@ -133,51 +135,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia case (const_idx) - ! If an index was found in the constituent hash table, then read in the data to that index of the constituent array - - var_found = .false. - field_data_ptr => cam_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call read_field(file, ccpp_required_data(req_idx), input_var_names(:,const_input_idx), 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - else - ! If not in standard names list, then just use constituent name as input file name: - call read_field(file, ccpp_required_data(req_idx), [ccpp_required_data(req_idx)], 'lev', timestep, & - field_data_ptr(:,:,constituent_idx), mark_as_read=.false., error_on_not_found=.false., var_found=var_found) - end if - if(.not. var_found) then - const_props => cam_model_const_properties() - constituent_has_default = .false. - call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - if (constituent_has_default) then - call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) - if (constituent_errflg /= 0) then - call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) - end if - field_data_ptr(:,:,constituent_idx) = constituent_default_value - if (masterproc) then - write(iulog,*) 'Consitituent ', trim(ccpp_required_data(req_idx)), ' initialized to default value: ', & - constituent_default_value - end if - else - field_data_ptr(:,:,constituent_idx) = 0._kind_phys - if (masterproc) then - write(iulog,*) 'Constituent ', trim(ccpp_required_data(req_idx)), ' default value not configured. Setting to 0.' - end if - end if - end if + ! If an index was found in the constituent hash table, then do nothing, this will be handled later case default @@ -212,6 +170,60 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia end do !CCPP suites + ! Read in constituent variables if not using init variables + field_data_ptr => cam_constituents_array() + const_props => cam_model_const_properties() + + ! Iterate over all registered constituents + do constituent_idx = 1, size(const_props) + var_found = .false. + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == trim(std_name))) then + ! Don't read the variable in if it's already initialized + if (is_initialized(std_name)) then + cycle + end if + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call read_field(file, std_name, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & + mark_as_read=.false., error_on_not_found=.false., var_found=var_found) + else + ! If not in standard names list, then just use constituent name as input file name: + call read_field(file, std_name, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), mark_as_read=.false., & + error_on_not_found=.false., var_found=var_found) + end if + if(.not. var_found) then + constituent_has_default = .false. + call const_props(constituent_idx)%has_default(constituent_has_default, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + if (constituent_has_default) then + call const_props(constituent_idx)%default_value(constituent_default_value, constituent_errflg, constituent_errmsg) + if (constituent_errflg /= 0) then + call endrun(constituent_errmsg, file=__FILE__, line=__LINE__) + end if + field_data_ptr(:,:,constituent_idx) = constituent_default_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' initialized to default value: ', constituent_default_value + end if + else + ! Intialize to constituent's configured minimum value + call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg) + field_data_ptr(:,:,constituent_idx) = constituent_min_value + if (masterproc) then + write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' + end if + end if + end if + end do + end subroutine physics_read_data subroutine physics_check_data(file_name, suite_names, timestep, min_difference, min_relative_value) @@ -219,7 +231,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use cam_abortutils, only: endrun use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: check_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array + use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_advected_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys use cam_logfile, only: iulog @@ -227,6 +239,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, use phys_vars_init_check, only: is_read_from_file use ioFileMod, only: cam_get_file use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t use phys_vars_init_check_simple, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len use physics_types_simple, only: slp, theta @@ -260,7 +273,9 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, logical :: file_found logical :: is_first logical :: is_read + character(len=std_name_len) :: std_name !Variable to hold constiutent standard name real(kind=kind_phys), pointer :: field_data_ptr(:,:,:) + type(ccpp_constituent_prop_ptr_t), pointer :: const_props(:) ! Initalize missing and non-initialized variables strings: missing_required_vars = ' ' @@ -299,25 +314,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! First check if the required variable is a constituent: call const_get_index(ccpp_required_data(req_idx), constituent_idx, abort=.false., warning=.false.) if (constituent_idx > -1) then - ! The required variable is a constituent. Call check variable routine on the relevant index of the constituent array - field_data_ptr => cam_advected_constituents_array() - - ! Check if constituent standard name in registered SIMA standard names list: - if(any(phys_var_stdnames == ccpp_required_data(req_idx))) then - ! Find array index to extract correct input names: - do n=1, phys_var_num - if(trim(phys_var_stdnames(n)) == trim(ccpp_required_data(req_idx))) then - const_input_idx = n - exit - end if - end do - call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - else - ! If not in standard names list, then just use constituent name as input file name: - call check_field(file, [ccpp_required_data(req_idx)], 'lev', timestep, field_data_ptr(:,:,constituent_idx), & - ccpp_required_data(req_idx), min_difference, min_relative_value, is_first) - end if + cycle else ! The required variable is not a constituent. Check if the variable was read from a file ! Find IC file input name array index for required variable: @@ -345,6 +342,29 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end do !CCPP suites + ! Check constituent variables + field_data_ptr => cam_advected_constituents_array() + const_props => cam_model_const_properties() + + do constituent_idx = 1, size(const_props) + ! Check if constituent standard name in registered SIMA standard names list: + call const_props(constituent_idx)%standard_name(std_name) + if(any(phys_var_stdnames == std_name)) then + ! Find array index to extract correct input names: + do n=1, phys_var_num + if(trim(phys_var_stdnames(n)) == trim(std_name)) then + const_input_idx = n + exit + end if + end do + call check_field(file, input_var_names(:,const_input_idx), 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, & + min_difference, min_relative_value, is_first) + else + ! If not in standard names list, then just use constituent name as input file name: + call check_field(file, [std_name], 'lev', timestep, field_data_ptr(:,:,constituent_idx), std_name, min_difference, min_relative_value, & + is_first) + end if + end do ! Close check file: call cam_pio_closefile(file) deallocate(file) diff --git a/test/unit/test_build_cache.py b/test/unit/test_build_cache.py index ed17d094..39dc59d2 100644 --- a/test/unit/test_build_cache.py +++ b/test/unit/test_build_cache.py @@ -425,9 +425,11 @@ def test_update_registry(self): ic_names = {"Only_had_a": ["heart", "brain"]} dycore = "banana" + constituents = ['cnst_1', 'cnst_2'] + #Update registry fields: test_cache.update_registry(tmp_test_reg, [tmp_test_reg], - dycore, [tmp_test_reg], ic_names) + dycore, [tmp_test_reg], ic_names, constituents) #Write updated fields to build cache file: test_cache.write() diff --git a/test/unit/test_cam_autogen.py b/test/unit/test_cam_autogen.py index 58f54daa..4a786aab 100644 --- a/test/unit/test_cam_autogen.py +++ b/test/unit/test_cam_autogen.py @@ -158,6 +158,10 @@ def ic_names(self): return {} + def constituents(self): + """Fake version of 'constituents' property.""" + return [] + # pylint: enable=no-self-use # pylint: enable=unused-argument @@ -515,7 +519,7 @@ def test_generate_registry(self): test_data_search = [os.path.join(_CAM_ROOT_DIR, "src", "data")] #Set expected output tuple: - expected_results = (f'{self.test_bldroot}'+os.sep+'cam_registry', False, [], {}) + expected_results = (f'{self.test_bldroot}'+os.sep+'cam_registry', False, [], {}, []) #Run registry generation function: gen_results = generate_registry(test_data_search, self.test_cache, _CAM_ROOT_DIR, @@ -670,7 +674,7 @@ def test_generate_init_routines(self): #Run init routines generation function: gen_path = generate_init_routines(self.test_cache, self.test_bldroot, False, False, - self.test_src_mods_dir, self.fort_indent, None, {}) + self.test_src_mods_dir, self.fort_indent, None, {}, []) #Check that the output path matches what is expected: self.assertEqual(gen_path, expected_path) diff --git a/test/unit/test_registry.py b/test/unit/test_registry.py index 0b6bb6c6..6fff5360 100644 --- a/test/unit/test_registry.py +++ b/test/unit/test_registry.py @@ -95,7 +95,7 @@ def test_good_simple_registry(self): out_meta = os.path.join(_TMP_DIR, out_source_name + '.meta') remove_files([out_source, out_meta]) # Run test - retcode, files, _ = gen_registry(filename, 'fv', _TMP_DIR, 2, + retcode, files, _, _ = gen_registry(filename, 'fv', _TMP_DIR, 2, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -156,7 +156,7 @@ def test_good_ddt_registry(self): out_meta = os.path.join(_TMP_DIR, out_meta_name) remove_files([out_source, out_meta]) # Run dycore - retcode, files, _ = gen_registry(filename, dycore, _TMP_DIR, 2, + retcode, files, _, _ = gen_registry(filename, dycore, _TMP_DIR, 2, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -203,7 +203,7 @@ def test_good_ddt_registry2(self): out_meta = os.path.join(_TMP_DIR, out_meta_name) remove_files([out_source, out_meta]) # Run dycore - retcode, files, _ = gen_registry(filename, 'se', _TMP_DIR, 2, + retcode, files, _, _ = gen_registry(filename, 'se', _TMP_DIR, 2, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -243,7 +243,7 @@ def test_good_array(self): out_meta = os.path.join(_TMP_DIR, out_meta_name) remove_files([out_source, out_meta]) # Run dycore - retcode, files, _ = gen_registry(filename, 'se', _TMP_DIR, 2, + retcode, files, _, _ = gen_registry(filename, 'se', _TMP_DIR, 2, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -281,7 +281,7 @@ def test_good_metadata_file_registry(self): out_meta = os.path.join(_TMP_DIR, out_name + '.meta') remove_files([out_source, out_meta]) # generate registry - retcode, files, _ = gen_registry(filename, 'se', _TMP_DIR, 2, + retcode, files, _, _ = gen_registry(filename, 'se', _TMP_DIR, 2, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -335,7 +335,7 @@ def test_diff_src_root_metadata_file_registry(self): shutil.copy(meta_file, tmp_src_dir) # Generate registry - retcode, files, _ = gen_registry(filename, 'se', _TMP_DIR, 2, + retcode, files, _, _ = gen_registry(filename, 'se', _TMP_DIR, 2, _SRC_MOD_DIR, _TMP_DIR, loglevel=logging.ERROR, error_on_no_validate=True) @@ -392,7 +392,7 @@ def test_SourceMods_metadata_file_registry(self): shutil.copy(meta_file, source_mod_file) # Generate registry - retcode, files, _ = gen_registry(filename, 'se', _TMP_DIR, 2, + retcode, files, _, _ = gen_registry(filename, 'se', _TMP_DIR, 2, tmp_src_dir, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -443,7 +443,7 @@ def test_good_complete_registry(self): remove_files([out_source, out_meta]) # Run test - retcode, files, _ = gen_registry(filename, 'se', _TMP_DIR, 2, + retcode, files, _, _ = gen_registry(filename, 'se', _TMP_DIR, 2, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -550,7 +550,7 @@ def test_parameter(self): # End for tree.write(filename) # Run test - retcode, files, _ = gen_registry(filename, 'eul', _TMP_DIR, 2, + retcode, files, _, _ = gen_registry(filename, 'eul', _TMP_DIR, 2, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) diff --git a/test/unit/test_write_init_files.py b/test/unit/test_write_init_files.py index d0736ee0..903df86d 100644 --- a/test/unit/test_write_init_files.py +++ b/test/unit/test_write_init_files.py @@ -175,7 +175,7 @@ def test_simple_reg_write_init(self): cap_database = capgen(run_env, return_db=True) # Generate physics initialization files: - retmsg = write_init.write_init_files(cap_database, {}, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -238,7 +238,7 @@ def test_simple_reg_constituent_write_init(self): check_init_out, phys_input_out]) # Generate registry files: - _, _, ic_names = gen_registry(filename, 'se', _TMP_DIR, 3, + _, _, ic_names, constituents = gen_registry(filename, 'se', _TMP_DIR, 3, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -258,7 +258,7 @@ def test_simple_reg_constituent_write_init(self): cap_database = capgen(run_env, return_db=True) # Generate physics initialization files: - retmsg = write_init.write_init_files(cap_database, ic_names, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, ic_names, constituents, _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -340,7 +340,7 @@ def test_no_reqvar_write_init(self): cap_database = capgen(run_env, return_db=True) # Generate physics initialization files: - retmsg = write_init.write_init_files(cap_database, {}, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -403,7 +403,7 @@ def test_protected_reg_write_init(self): check_init_out, phys_input_out]) # Generate registry files: - _, files, _ = gen_registry(filename, 'se', _TMP_DIR, 3, + _, files, _, _ = gen_registry(filename, 'se', _TMP_DIR, 3, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -423,7 +423,7 @@ def test_protected_reg_write_init(self): cap_database = capgen(run_env, return_db=True) # Generate physics initialization files: - retmsg = write_init.write_init_files(cap_database, {}, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -507,7 +507,7 @@ def test_host_input_var_write_init(self): cap_database = capgen(run_env, return_db=True) # Generate physics initialization files: - retmsg = write_init.write_init_files(cap_database, {}, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -572,7 +572,7 @@ def test_no_horiz_var_write_init(self): remove_files([out_source, out_meta, cap_datafile, check_init_out, phys_input_out]) # Generate registry files: - _, files, _ = gen_registry(filename, 'se', _TMP_DIR, 3, + _, files, _, _ = gen_registry(filename, 'se', _TMP_DIR, 3, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -592,7 +592,7 @@ def test_no_horiz_var_write_init(self): cap_database = capgen(run_env, return_db=True) # Run test - _ = write_init.write_init_files(cap_database, {}, _TMP_DIR, + _ = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -647,7 +647,7 @@ def test_scalar_var_write_init(self): check_init_out, phys_input_out]) # Generate registry files: - _, files, _ = gen_registry(filename, 'se', _TMP_DIR, 3, + _, files, _, _ = gen_registry(filename, 'se', _TMP_DIR, 3, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -667,7 +667,7 @@ def test_scalar_var_write_init(self): cap_database = capgen(run_env, return_db=True) # Run test - _ = write_init.write_init_files(cap_database, {}, _TMP_DIR, + _ = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -722,7 +722,7 @@ def test_4d_var_write_init(self): check_init_out, phys_input_out]) # Generate registry files: - _, files, _ = gen_registry(filename, 'se', _TMP_DIR, 3, + _, files, _, _ = gen_registry(filename, 'se', _TMP_DIR, 3, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -741,7 +741,7 @@ def test_4d_var_write_init(self): cap_database = capgen(run_env, return_db=True) # Run test - retmsg = write_init.write_init_files(cap_database, {}, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -815,7 +815,7 @@ def test_ddt_reg_write_init(self): cap_database = capgen(run_env, return_db=True) # Generate physics initialization files: - retmsg = write_init.write_init_files(cap_database, {}, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -878,7 +878,7 @@ def test_ddt2_reg_write_init(self): check_init_out, phys_input_out]) # Generate registry files: - _, files, _ = gen_registry(filename, 'se', _TMP_DIR, 3, + _, files, _, _ = gen_registry(filename, 'se', _TMP_DIR, 3, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -897,7 +897,7 @@ def test_ddt2_reg_write_init(self): cap_database = capgen(run_env, return_db=True) # Generate physics initialization files: - retmsg = write_init.write_init_files(cap_database, {}, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -959,7 +959,7 @@ def test_ddt_array_reg_write_init(self): check_init_out, phys_input_out]) # Generate registry files: - _, _, ic_names = gen_registry(filename, 'se', _TMP_DIR, 3, + _, _, ic_names, _ = gen_registry(filename, 'se', _TMP_DIR, 3, _SRC_MOD_DIR, _CAM_ROOT, loglevel=logging.ERROR, error_on_no_validate=True) @@ -978,7 +978,7 @@ def test_ddt_array_reg_write_init(self): cap_database = capgen(run_env, return_db=True) # Generate physics initialization files: - retmsg = write_init.write_init_files(cap_database, ic_names, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, ic_names, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -1059,7 +1059,7 @@ def test_meta_file_reg_write_init(self): cap_database = capgen(run_env, return_db=True) # Generate physics initialization files: - retmsg = write_init.write_init_files(cap_database, {}, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -1140,7 +1140,7 @@ def test_parameter_reg_write_init(self): cap_database = capgen(run_env, return_db=True) # Generate physics initialization files: - retmsg = write_init.write_init_files(cap_database, {}, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name, @@ -1224,7 +1224,7 @@ def test_bad_vertical_dimension(self): cap_database = capgen(run_env, return_db=True) # Run test - retmsg = write_init.write_init_files(cap_database, {}, _TMP_DIR, + retmsg = write_init.write_init_files(cap_database, {}, [], _TMP_DIR, find_file, _INC_SEARCH_DIRS, 3, logger, phys_check_filename=vic_name,