diff --git a/src/data/write_init_files.py b/src/data/write_init_files.py index 55728d4c..74b8d877 100644 --- a/src/data/write_init_files.py +++ b/src/data/write_init_files.py @@ -766,6 +766,9 @@ def get_dimension_info(hvar): - Flag if any dimensions are number_of_ccpp_constituents and needs reading separate variables by constituent and reassembled into host model indices. + - Flag if the variable is (horizontal, fixed-size extra dimension) and + needs reading separate numbered per-slice variables + (). """ vdim_name = None legal_dims = False @@ -774,6 +777,13 @@ def get_dimension_info(hvar): dims = hvar.get_dimensions() levnm = hvar.has_vertical_dimension() has_constituent_dim = any('number_of_ccpp_constituents' in dim for dim in dims) + # A (horizontal, extra) variable whose only extra dimension is a fixed-size, + # non-vertical dimension (e.g. dust_size_bin_dimension) is read from numbered + # per-slice file variables (a fixed extra dimension cannot be captured as a + # single history/snapshot variable on the CAM side): + has_indexed_dim = ((len(dims) == 2) and (not levnm) and + (not has_constituent_dim) and + is_horizontal_dimension(dims[0])) # is only 'legal' for 2 or 3 dimensional fields (i.e., 1 or 2 # dimensional variables). @@ -797,6 +807,12 @@ def get_dimension_info(hvar): # based on constituent name. # This case will be handled separately. legal_dims = True + elif has_indexed_dim: + # A special case where the only extra dimension is a fixed-size, + # non-vertical dimension: the variable is read from numbered + # per-slice file variables, . + # This case will be handled separately. + legal_dims = True elif (ldims > 3) or ((ldims > 1) and (not levnm)): # The regular case where the second dimension must be vertical, # and dimensions greater than three are unsupported. @@ -865,7 +881,7 @@ def get_dimension_info(hvar): # end if # end if - return vdim_name, legal_dims, fail_reason, has_constituent_dim + return vdim_name, legal_dims, fail_reason, has_constituent_dim, has_indexed_dim def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports, phys_check_fname_str, constituent_set, @@ -907,7 +923,7 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports, call_string_key = f"case ('{var_stdname}')" # Extract vertical level variable: - levnm, call_read_field, reason, has_constituent_read = get_dimension_info(hvar) + levnm, call_read_field, reason, has_constituent_read, has_indexed_read = get_dimension_info(hvar) if hvar.get_prop_value('protected'): call_read_field = False if reason: @@ -924,6 +940,10 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports, if has_constituent_read: # Special case for constituent-dimension variables. call_str = f"call read_constituent_dimensioned_field(const_props, file, '{var_stdname}', input_var_names(:,name_idx), " + elif has_indexed_read: + # Special case for fixed-size indexed-dimension variables + # (read from numbered per-slice file variables). + call_str = f"call read_indexed_dimensioned_field(file, '{var_stdname}', input_var_names(:,name_idx), " else: # Replace vertical dimension with local name call_str = "call read_field(file, " + \ @@ -970,7 +990,8 @@ 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", - "read_constituent_dimensioned_field"]], + "read_constituent_dimensioned_field", + "read_indexed_dimensioned_field"]], ["cam_ccpp_cap", ["ccpp_physics_suite_variables", "cam_constituents_array", "cam_model_const_properties"]], @@ -1268,20 +1289,35 @@ def write_phys_check_subroutine(outfile, host_dict, host_vars, host_imports, call_string_key = f"case ('{var_stdname}')" # Extract vertical level variable: - levnm, call_check_field, reason, has_constituent_read = get_dimension_info(hvar) + levnm, call_check_field, reason, has_constituent_read, has_indexed_read = get_dimension_info(hvar) + + # Constituent-indexed fields are checked per constituent against + # _ file variables (mirroring the + # read_constituent_dimensioned_field call in physics_read_data), + # with and without a vertical dimension. - # If this is a constituent-indexed field, do not check it for now. - if has_constituent_read: + # Indexed-dimensioned (fixed-size extra dimension) fields are read-only + # inputs assembled from numbered per-slice file variables; checking is + # not implemented for them (mirroring the 2-D constituent skip above). + if has_indexed_read: continue # end if # Set "check_field" call string: if call_check_field: - call_str = "call check_field(file, input_var_names(:,name_idx), " + if has_constituent_read: + # Special case for constituent-dimension variables. + call_str = f"call check_constituent_dimensioned_field(const_props, file, '{var_stdname}', input_var_names(:,name_idx), " + else: + call_str = "call check_field(file, input_var_names(:,name_idx), " + # end if if levnm is not None: call_str += f"'{levnm}', " # end if - call_str += f"timestep, {var_locname}, '{var_stdname}', " + call_str += f"timestep, {var_locname}, " + if not has_constituent_read: + call_str += f"'{var_stdname}', " + # end if call_str += "min_difference, min_relative_value, is_first, diff_found)" else: # For check field, don't endrun @@ -1305,6 +1341,7 @@ 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", + "check_constituent_dimensioned_field", "flush_check_field_verbose"]], ["cam_ccpp_cap", ["ccpp_physics_suite_variables", "cam_constituents_array", @@ -1412,6 +1449,10 @@ def write_phys_check_subroutine(outfile, host_dict, host_vars, host_imports, outfile.write("call cam_pio_openfile(file, ncdata_check_loc, " + \ "pio_nowrite, log_info=.false.)", 2) + # Constituent properties are needed inside the suite loop by + # check_constituent_dimensioned_field, and below for the constituent checks: + outfile.write("const_props => cam_model_const_properties()", 2) + # Loop over physics suites: outfile.comment("Loop over CCPP physics/chemistry suites:", 2) outfile.write("do suite_idx = 1, size(suite_names, 1)", 2) @@ -1493,7 +1534,6 @@ def write_phys_check_subroutine(outfile, host_dict, host_vars, host_imports, outfile.blank_line() outfile.comment("Check constituent variables", 2) outfile.write("field_data_ptr => cam_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) diff --git a/src/physics/utils/physics_data.F90 b/src/physics/utils/physics_data.F90 index 2ae08c51..218dc2cf 100644 --- a/src/physics/utils/physics_data.F90 +++ b/src/physics/utils/physics_data.F90 @@ -6,7 +6,9 @@ module physics_data public :: find_input_name_idx public :: read_field public :: read_constituent_dimensioned_field + public :: read_indexed_dimensioned_field public :: check_field + public :: check_constituent_dimensioned_field public :: flush_check_field_verbose ! Non-standard variable indices: @@ -28,9 +30,15 @@ module physics_data end interface check_field interface read_constituent_dimensioned_field - module procedure read_constituent_dimensioned_field_2d + module procedure read_constituent_dimensioned_field_2d !horizontal columns only (1-D buffer per constituent) + module procedure read_constituent_dimensioned_field_3d !horizontal columns + vertical levels (2-D buffer per constituent) end interface read_constituent_dimensioned_field + interface check_constituent_dimensioned_field + module procedure check_constituent_dimensioned_field_2d !horizontal columns only (1-D buffer per constituent) + module procedure check_constituent_dimensioned_field_3d !horizontal columns + vertical levels (2-D buffer per constituent) + end interface check_constituent_dimensioned_field + ! Module-level storage for verbose check_field entries. ! These are accumulated during check_field calls and flushed ! at the end via flush_check_field_verbose, so that the verbose @@ -695,6 +703,666 @@ function constituent_dim_file_var_names(base_name, cname) result(var_names) end function constituent_dim_file_var_names + ! Vertically-resolved analog of read_constituent_dimensioned_field_2d: reads a + ! (horizontal, vertical, constituent) field where each constituent is stored on + ! file as a separate _ variable (so the CAM + ! <-> CAM-SIMA constituent-index reshuffle is handled by name). vcoord_name is + ! the vertical coordinate ('lev' or 'ilev'), emitted by write_init_files.py for + ! constituent-dimensioned variables that also carry a vertical dimension. + subroutine read_constituent_dimensioned_field_3d(const_props, file, std_name, base_var_names, vcoord_name, timestep, field_array, error_on_not_found) + use ccpp_kinds, only: kind_phys + use shr_assert_mod, only: shr_assert_in_domain + use shr_sys_mod, only: shr_sys_flush + use pio, only: file_desc_t, var_desc_t + use spmd_utils, only: masterproc + use cam_pio_utils, only: cam_pio_find_var + use cam_abortutils, only: endrun, check_allocate + use cam_logfile, only: iulog + use cam_field_read, only: cam_read_field + use vert_coord, only: pver, pverp + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t + use phys_vars_init_check, only: mark_as_read_from_file + use phys_vars_init_check, only: phys_var_stdnames, input_var_names, phys_var_num + use string_utils, only: to_lower + + ! Dummy arguments + type(ccpp_constituent_prop_ptr_t), intent(in) :: const_props(:) ! Constituent properties + type(file_desc_t), intent(inout) :: file !Parallel I/O (PIO) file type. + character(len=*), intent(in) :: std_name ! Standard name of base variable. + character(len=*), intent(in) :: base_var_names(:) ! "Base" name(s) used to construct variable name (base_constname) + character(len=*), intent(in) :: vcoord_name ! Vertical coordinate name ('lev' or 'ilev') + integer, intent(in) :: timestep ! Timestep to read [count] + real(kind_phys), intent(inout) :: field_array(:,:,:) ! Output field array (ncol, nlev, pcnst) + logical, optional, intent(in) :: error_on_not_found ! Flag to error and exit if not found + + ! Local variables + logical :: var_found + character(len=128) :: constituent_name + character(len=256) :: file_var_name + character(len=256) :: found_name + character(len=512) :: missing_vars + type(var_desc_t) :: vardesc + real(kind_phys), allocatable :: buffer(:,:) + integer :: const_idx, base_idx + integer :: num_levs + integer :: ierr + logical :: error_on_not_found_local + logical :: any_missing + + ! For construction of constituent short name mapping + character(len=128), allocatable :: constituent_short_names(:) + character(len=128) :: constituent_std_name + integer :: n + integer :: const_input_idx + + character(len=256) :: errmsg + + character(len=*), parameter :: subname = 'read_constituent_dimensioned_field: ' + + if (present(error_on_not_found)) then + error_on_not_found_local = error_on_not_found + else + error_on_not_found_local = .true. + end if + + ! Resolve the vertical extent from the coordinate name. + if (trim(vcoord_name) == 'lev') then + num_levs = pver + else if (trim(vcoord_name) == 'ilev') then + num_levs = pverp + else + call endrun(subname//'Unknown vcoord_name, '//trim(vcoord_name)) + end if + + ! Initialize tracking variables + any_missing = .false. + missing_vars = '' + + ! Allocate temporary buffer + allocate(buffer(size(field_array, 1), num_levs), stat=ierr, errmsg=errmsg) + call check_allocate(ierr, subname, 'buffer', errmsg=errmsg) + + !REMOVECAM: + ! Because the constituent properties pointer contains standard names, and not input constituent names + ! (e.g., Q, CLDLIQ, ...) which are used in the input file names, + ! we have to construct a mapping of the standard names to the short input IC file names + ! When CAM is retired and only standard names are used for constituents, this mapping can be removed. + allocate(constituent_short_names(size(const_props)), stat=ierr, errmsg=errmsg) + call check_allocate(ierr, subname, 'constituent_short_names', errmsg=errmsg) + + const_shortmap_loop: do const_idx = 1, size(const_props) + ! Get constituent standard name. + call const_props(const_idx)%standard_name(constituent_std_name) + + ! Check if constituent standard name is in the registry to look up its IC name + ! n.b. this assumes that the first IC name specified in the registry for this constituent + ! is the short name + const_input_idx = -1 + phys_inputvar_loop: do n = 1, phys_var_num + ! case-insensitive: see find_input_name_idx + if (to_lower(trim(phys_var_stdnames(n))) == to_lower(trim(constituent_std_name))) then + const_input_idx = n + exit phys_inputvar_loop + end if + end do phys_inputvar_loop + + if (const_input_idx > 0) then + ! Use the first entry from the input_var_names -- assumed to be short name. + constituent_short_names(const_idx) = trim(input_var_names(1, const_input_idx)) + else + ! Use the standard name itself if not found in registry. + constituent_short_names(const_idx) = trim(constituent_std_name) + end if + end do const_shortmap_loop + !END REMOVECAM + + ! Loop through all possible base names to find correct base name. + ! Note this assumes that the same base name is used for all constituents. + ! i.e., there cannot be something like cam_in_cflx_Q & cflx_CLDLIQ in one file. + base_idx_loop: do base_idx = 1, size(base_var_names) + ! Loop through all constituents + const_idx_loop: do const_idx = 1, size(const_props) + ! Get constituent short name + constituent_name = constituent_short_names(const_idx) + + ! Try to find variable in file: _, + ! trying case variants of the constituent name (see + ! constituent_dim_file_var_names). + var_found = .false. + call cam_pio_find_var(file, & + constituent_dim_file_var_names(base_var_names(base_idx), & + constituent_name), & + found_name, vardesc, var_found) + + if(var_found) then + exit base_idx_loop + endif + end do const_idx_loop + end do base_idx_loop + + if(.not. var_found) then + if(error_on_not_found_local) then + !End model run with appropriate error message: + call endrun(subname // 'Required constituent-dimensioned variables not found: No match for ' // trim(std_name)) + else + !Write message to log file, then exit subroutine: + if (masterproc) then + write(iulog, *) subname // 'Required constituent-dimensioned variables not found: No match for ' // trim(std_name) + call shr_sys_flush(iulog) + end if + return !Nothing more to do here + end if + end if + + ! Once base_idx is identified, use it in the actual constituent loop: + const_read_loop: do const_idx = 1, size(const_props) + ! Get constituent short name + constituent_name = constituent_short_names(const_idx) + + ! Create file variable name (used for reporting): _ + file_var_name = trim(base_var_names(base_idx)) // '_' // trim(constituent_name) + + ! Try to find variable in file, trying case variants of the + ! constituent name (see constituent_dim_file_var_names). + var_found = .false. + call cam_pio_find_var(file, & + constituent_dim_file_var_names(base_var_names(base_idx), & + constituent_name), & + found_name, vardesc, var_found) + + ! Some constituents whose names are not specified in the registry + ! will have cnst_ prepended to them (e.g., cnst_dst_a1); also try reading + ! from file by removing this prefix: + if (.not. var_found) then + if (constituent_name(1:5) == 'cnst_') then + call cam_pio_find_var(file, & + constituent_dim_file_var_names(base_var_names(base_idx), & + constituent_name(6:)), & + found_name, vardesc, var_found) + end if + end if + + if (var_found) then + ! Read the variable + if (masterproc) then + write(iulog, *) 'Reading constituent-dimensioned input field, ', trim(found_name) + call shr_sys_flush(iulog) + end if + + call cam_read_field(found_name, file, buffer, var_found, & + timelevel=timestep, dim3name=trim(vcoord_name), & + dim3_bnds=[1, num_levs]) + + if (var_found) then + ! Copy to correct constituent index in field array + field_array(:, :, const_idx) = buffer(:, :) + + ! Check for NaN values + call shr_assert_in_domain(field_array(:, :, const_idx), is_nan=.false., & + varname=trim(found_name), & + msg=subname//'NaN found in '//trim(found_name)) + else + ! Failed to read even though variable was found + any_missing = .true. + if (len_trim(missing_vars) > 0) then + missing_vars = trim(missing_vars) // ', ' // trim(file_var_name) + else + missing_vars = trim(file_var_name) + end if + end if + else + ! Variable not found in file + any_missing = .true. + if (len_trim(missing_vars) > 0) then + missing_vars = trim(missing_vars) // ', ' // trim(file_var_name) + else + missing_vars = trim(file_var_name) + end if + + if (.not. error_on_not_found_local) then + ! Use default value (already set at initialization) + + if (masterproc) then + write(iulog, *) 'Constituent-dimensioned field ', trim(file_var_name), & + ' not found, using default value for constituent ', trim(constituent_name) + call shr_sys_flush(iulog) + end if + end if + end if + end do const_read_loop + + ! Check if we should fail due to missing variables + if (any_missing .and. error_on_not_found_local) then + call endrun(subname//'Required constituent-dimensioned variables not found: ' // trim(missing_vars) // & + 'Make sure the constituent short name is the first in the list in the registry.') + end if + + ! Mark the base variable as read from file (only if no errors) + call mark_as_read_from_file(std_name) + + ! Clean up + deallocate(constituent_short_names) + deallocate(buffer) + + end subroutine read_constituent_dimensioned_field_3d + + ! Reads a (horizontal, N) field whose trailing dimension is a fixed-size, + ! non-vertical dimension (e.g., dust emission size bins): each slice is stored + ! on file as a separate numbered variable (e.g., + ! cam_in_dstflx_bin1 ... cam_in_dstflx_bin4), because a fixed extra dimension + ! cannot be captured as a single history/snapshot variable. The slice index is + ! appended directly to the base name, so the base names given in the registry + ! must carry any separator text (e.g., 'cam_in_dstflx_bin'). + ! The number of slices is taken from the trailing dimension of field_array. + subroutine read_indexed_dimensioned_field(file, std_name, base_var_names, timestep, field_array, error_on_not_found) + use ccpp_kinds, only: kind_phys + use shr_assert_mod, only: shr_assert_in_domain + use shr_sys_mod, only: shr_sys_flush + use pio, only: file_desc_t, var_desc_t + use spmd_utils, only: masterproc + use cam_pio_utils, only: cam_pio_find_var + use cam_abortutils, only: endrun, check_allocate + use cam_logfile, only: iulog + use cam_field_read, only: cam_read_field + use phys_vars_init_check, only: mark_as_read_from_file + + ! Dummy arguments + type(file_desc_t), intent(inout) :: file !Parallel I/O (PIO) file type. + character(len=*), intent(in) :: std_name ! Standard name of base variable. + character(len=*), intent(in) :: base_var_names(:) ! "Base" name(s) used to construct variable name (base_varname) + integer, intent(in) :: timestep ! Timestep to read [count] + real(kind_phys), intent(inout) :: field_array(:,:) ! Output field array (ncol, indexed dimension) + logical, optional, intent(in) :: error_on_not_found ! Flag to error and exit if not found + + ! Local variables + logical :: var_found + character(len=256) :: file_var_name + character(len=256) :: found_name + character(len=512) :: missing_vars + type(var_desc_t) :: vardesc + real(kind_phys), allocatable :: buffer(:) + integer :: slice_idx, base_idx + integer :: ierr + logical :: error_on_not_found_local + logical :: any_missing + + character(len=256) :: errmsg + + character(len=*), parameter :: subname = 'read_indexed_dimensioned_field: ' + + if (present(error_on_not_found)) then + error_on_not_found_local = error_on_not_found + else + error_on_not_found_local = .true. + end if + + ! Initialize tracking variables + any_missing = .false. + missing_vars = '' + + ! Allocate temporary buffer + allocate(buffer(size(field_array, 1)), stat=ierr, errmsg=errmsg) + call check_allocate(ierr, subname, 'buffer', errmsg=errmsg) + + ! Loop through all possible base names to find correct base name. + ! Note this assumes that the same base name is used for all slices. + base_idx_loop: do base_idx = 1, size(base_var_names) + ! Loop through all slices of the indexed dimension + slice_idx_loop: do slice_idx = 1, size(field_array, 2) + ! Create file variable name: + write(file_var_name, '(a,i0)') trim(base_var_names(base_idx)), slice_idx + + ! Try to find variable in file + var_found = .false. + call cam_pio_find_var(file, [file_var_name], found_name, vardesc, var_found) + + if(var_found) then + exit base_idx_loop + endif + end do slice_idx_loop + end do base_idx_loop + + if(.not. var_found) then + if(error_on_not_found_local) then + !End model run with appropriate error message: + call endrun(subname // 'Required indexed-dimensioned variables not found: No match for ' // trim(std_name)) + else + !Write message to log file, then exit subroutine: + if (masterproc) then + write(iulog, *) subname // 'Required indexed-dimensioned variables not found: No match for ' // trim(std_name) + call shr_sys_flush(iulog) + end if + return !Nothing more to do here + end if + end if + + ! Once base_idx is identified, use it in the actual slice loop: + slice_read_loop: do slice_idx = 1, size(field_array, 2) + ! Create file variable name: + write(file_var_name, '(a,i0)') trim(base_var_names(base_idx)), slice_idx + + ! Try to find variable in file + var_found = .false. + call cam_pio_find_var(file, [file_var_name], found_name, vardesc, var_found) + + if (var_found) then + ! Read the variable + if (masterproc) then + write(iulog, *) 'Reading indexed-dimensioned input field, ', trim(found_name) + call shr_sys_flush(iulog) + end if + + call cam_read_field(found_name, file, buffer, var_found, timelevel=timestep) + + if (var_found) then + ! Copy to correct slice index in field array + field_array(:, slice_idx) = buffer(:) + + ! Check for NaN values + call shr_assert_in_domain(field_array(:, slice_idx), is_nan=.false., & + varname=trim(found_name), & + msg=subname//'NaN found in '//trim(found_name)) + else + ! Failed to read even though variable was found + any_missing = .true. + if (len_trim(missing_vars) > 0) then + missing_vars = trim(missing_vars) // ', ' // trim(file_var_name) + else + missing_vars = trim(file_var_name) + end if + end if + else + ! Variable not found in file + any_missing = .true. + if (len_trim(missing_vars) > 0) then + missing_vars = trim(missing_vars) // ', ' // trim(file_var_name) + else + missing_vars = trim(file_var_name) + end if + + if (.not. error_on_not_found_local) then + ! Use default value (already set at initialization) + + if (masterproc) then + write(iulog, *) 'Indexed-dimensioned field ', trim(file_var_name), & + ' not found, using default value for this slice' + call shr_sys_flush(iulog) + end if + end if + end if + end do slice_read_loop + + ! Check if we should fail due to missing variables + if (any_missing .and. error_on_not_found_local) then + call endrun(subname//'Required indexed-dimensioned variables not found: ' // trim(missing_vars) // & + '. Make sure the in the registry hold the numbered-variable prefix.') + end if + + ! Mark the base variable as read from file (only if no errors) + call mark_as_read_from_file(std_name) + + ! Clean up + deallocate(buffer) + + end subroutine read_indexed_dimensioned_field + + ! Check analog of read_constituent_dimensioned_field_3d: compares each slice of + ! a (horizontal, vertical, constituent) field against the per-constituent + ! _ variables on the check file, via the same + ! constituent-name resolution as the read. Constituents whose variable is not on + ! the check file are skipped silently (the file only carries the species the + ! capture wrote), so slices that were never read/compared -- including any + ! poisoned non-cluster slots -- are not reported as differences. Each compared + ! slice is labeled by its file variable name in the check output. + subroutine check_constituent_dimensioned_field_2d(const_props, file, std_name, base_var_names, & + timestep, field_array, min_difference, min_relative_value, is_first, diff_found) + use ccpp_kinds, only: kind_phys + use pio, only: file_desc_t, var_desc_t + use cam_pio_utils, only: cam_pio_find_var + use cam_abortutils, only: check_allocate + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t + use phys_vars_init_check, only: phys_var_stdnames, input_var_names, phys_var_num + use string_utils, only: to_lower + + ! Dummy arguments + type(ccpp_constituent_prop_ptr_t), intent(in) :: const_props(:) ! Constituent properties + type(file_desc_t), intent(inout) :: file ! Parallel I/O (PIO) file type + character(len=*), intent(in) :: std_name ! Standard name of base variable + character(len=*), intent(in) :: base_var_names(:) ! "Base" name(s) used to construct variable name (base_constname) + integer, intent(in) :: timestep ! Timestep to check [count] + real(kind_phys), intent(in) :: field_array(:,:) ! Field array to check (ncol, pcnst) + real(kind_phys), intent(in) :: min_difference + real(kind_phys), intent(in) :: min_relative_value + logical, intent(inout) :: is_first + logical, intent(out) :: diff_found + + ! Local variables + logical :: var_found + logical :: slice_diff_found + character(len=128) :: constituent_name + character(len=256) :: found_name + type(var_desc_t) :: vardesc + integer :: const_idx + integer :: ierr + + ! For construction of constituent short name mapping + character(len=128), allocatable :: constituent_short_names(:) + character(len=128) :: constituent_std_name + integer :: n + integer :: const_input_idx + + character(len=256) :: errmsg + + character(len=*), parameter :: subname = 'check_constituent_dimensioned_field: ' + + diff_found = .false. + + !REMOVECAM: + ! Same standard-name -> short-input-name mapping as + ! read_constituent_dimensioned_field, so the check resolves exactly the file + ! variable names the read used. When CAM is retired and only standard names + ! are used for constituents, this mapping can be removed. + allocate(constituent_short_names(size(const_props)), stat=ierr, errmsg=errmsg) + call check_allocate(ierr, subname, 'constituent_short_names', errmsg=errmsg) + + const_shortmap_loop: do const_idx = 1, size(const_props) + ! Get constituent standard name. + call const_props(const_idx)%standard_name(constituent_std_name) + + ! Check if constituent standard name is in the registry to look up its IC name + ! n.b. this assumes that the first IC name specified in the registry for this constituent + ! is the short name + const_input_idx = -1 + phys_inputvar_loop: do n = 1, phys_var_num + ! case-insensitive: see find_input_name_idx + if (to_lower(trim(phys_var_stdnames(n))) == to_lower(trim(constituent_std_name))) then + const_input_idx = n + exit phys_inputvar_loop + end if + end do phys_inputvar_loop + + if (const_input_idx > 0) then + ! Use the first entry from the input_var_names -- assumed to be short name. + constituent_short_names(const_idx) = trim(input_var_names(1, const_input_idx)) + else + ! Use the standard name itself if not found in registry. + constituent_short_names(const_idx) = trim(constituent_std_name) + end if + end do const_shortmap_loop + !END REMOVECAM + + const_check_loop: do const_idx = 1, size(const_props) + ! Get constituent short name + constituent_name = constituent_short_names(const_idx) + + ! Search for _, trying all base names + ! (the read assumes one base name serves all constituents, so the first + ! hit is used) and the case variants of the constituent name (see + ! constituent_dim_file_var_names). + var_found = .false. + base_idx_loop: do n = 1, size(base_var_names) + call cam_pio_find_var(file, & + constituent_dim_file_var_names(base_var_names(n), & + constituent_name), & + found_name, vardesc, var_found) + if (var_found) exit base_idx_loop + + ! Some constituents whose names are not specified in the registry + ! will have cnst_ prepended to them (e.g., cnst_dst_a1); also try + ! matching on the file by removing this prefix: + if (constituent_name(1:5) == 'cnst_') then + call cam_pio_find_var(file, & + constituent_dim_file_var_names(base_var_names(n), & + constituent_name(6:)), & + found_name, vardesc, var_found) + if (var_found) exit base_idx_loop + end if + end do base_idx_loop + + ! Constituent slices without a matching variable on the check file are + ! skipped: the capture only writes the species the source model carries. + if (.not. var_found) cycle const_check_loop + + ! Pass the resolved per-constituent name as both the search name and the + ! reporting label, so check_field's standard-name fallback search cannot + ! match an unrelated variable and diffs are reported per constituent. + call check_field(file, [found_name], timestep, & + field_array(:, const_idx), trim(found_name), & + min_difference, min_relative_value, is_first, slice_diff_found) + if (slice_diff_found) then + diff_found = .true. + end if + end do const_check_loop + + deallocate(constituent_short_names) + + end subroutine check_constituent_dimensioned_field_2d + + subroutine check_constituent_dimensioned_field_3d(const_props, file, std_name, base_var_names, & + vcoord_name, timestep, field_array, min_difference, min_relative_value, is_first, diff_found) + use ccpp_kinds, only: kind_phys + use pio, only: file_desc_t, var_desc_t + use cam_pio_utils, only: cam_pio_find_var + use cam_abortutils, only: check_allocate + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t + use phys_vars_init_check, only: phys_var_stdnames, input_var_names, phys_var_num + use string_utils, only: to_lower + + ! Dummy arguments + type(ccpp_constituent_prop_ptr_t), intent(in) :: const_props(:) ! Constituent properties + type(file_desc_t), intent(inout) :: file ! Parallel I/O (PIO) file type + character(len=*), intent(in) :: std_name ! Standard name of base variable + character(len=*), intent(in) :: base_var_names(:) ! "Base" name(s) used to construct variable name (base_constname) + character(len=*), intent(in) :: vcoord_name ! Vertical coordinate name ('lev' or 'ilev') + integer, intent(in) :: timestep ! Timestep to check [count] + real(kind_phys), intent(in) :: field_array(:,:,:) ! Field array to check (ncol, nlev, pcnst) + real(kind_phys), intent(in) :: min_difference + real(kind_phys), intent(in) :: min_relative_value + logical, intent(inout) :: is_first + logical, intent(out) :: diff_found + + ! Local variables + logical :: var_found + logical :: slice_diff_found + character(len=128) :: constituent_name + character(len=256) :: found_name + type(var_desc_t) :: vardesc + integer :: const_idx + integer :: ierr + + ! For construction of constituent short name mapping + character(len=128), allocatable :: constituent_short_names(:) + character(len=128) :: constituent_std_name + integer :: n + integer :: const_input_idx + + character(len=256) :: errmsg + + character(len=*), parameter :: subname = 'check_constituent_dimensioned_field: ' + + diff_found = .false. + + !REMOVECAM: + ! Same standard-name -> short-input-name mapping as + ! read_constituent_dimensioned_field, so the check resolves exactly the file + ! variable names the read used. When CAM is retired and only standard names + ! are used for constituents, this mapping can be removed. + allocate(constituent_short_names(size(const_props)), stat=ierr, errmsg=errmsg) + call check_allocate(ierr, subname, 'constituent_short_names', errmsg=errmsg) + + const_shortmap_loop: do const_idx = 1, size(const_props) + ! Get constituent standard name. + call const_props(const_idx)%standard_name(constituent_std_name) + + ! Check if constituent standard name is in the registry to look up its IC name + ! n.b. this assumes that the first IC name specified in the registry for this constituent + ! is the short name + const_input_idx = -1 + phys_inputvar_loop: do n = 1, phys_var_num + ! case-insensitive: see find_input_name_idx + if (to_lower(trim(phys_var_stdnames(n))) == to_lower(trim(constituent_std_name))) then + const_input_idx = n + exit phys_inputvar_loop + end if + end do phys_inputvar_loop + + if (const_input_idx > 0) then + ! Use the first entry from the input_var_names -- assumed to be short name. + constituent_short_names(const_idx) = trim(input_var_names(1, const_input_idx)) + else + ! Use the standard name itself if not found in registry. + constituent_short_names(const_idx) = trim(constituent_std_name) + end if + end do const_shortmap_loop + !END REMOVECAM + + const_check_loop: do const_idx = 1, size(const_props) + ! Get constituent short name + constituent_name = constituent_short_names(const_idx) + + ! Search for _, trying all base names + ! (the read assumes one base name serves all constituents, so the first + ! hit is used) and the case variants of the constituent name (see + ! constituent_dim_file_var_names). + var_found = .false. + base_idx_loop: do n = 1, size(base_var_names) + call cam_pio_find_var(file, & + constituent_dim_file_var_names(base_var_names(n), & + constituent_name), & + found_name, vardesc, var_found) + if (var_found) exit base_idx_loop + + ! Some constituents whose names are not specified in the registry + ! will have cnst_ prepended to them (e.g., cnst_dst_a1); also try + ! matching on the file by removing this prefix: + if (constituent_name(1:5) == 'cnst_') then + call cam_pio_find_var(file, & + constituent_dim_file_var_names(base_var_names(n), & + constituent_name(6:)), & + found_name, vardesc, var_found) + if (var_found) exit base_idx_loop + end if + end do base_idx_loop + + ! Constituent slices without a matching variable on the check file are + ! skipped: the capture only writes the species the source model carries. + if (.not. var_found) cycle const_check_loop + + ! Pass the resolved per-constituent name as both the search name and the + ! reporting label, so check_field's standard-name fallback search cannot + ! match an unrelated variable and diffs are reported per constituent. + call check_field(file, [found_name], vcoord_name, timestep, & + field_array(:, :, const_idx), trim(found_name), & + min_difference, min_relative_value, is_first, slice_diff_found) + if (slice_diff_found) then + diff_found = .true. + end if + end do const_check_loop + + deallocate(constituent_short_names) + + end subroutine check_constituent_dimensioned_field_3d + subroutine check_field_2d(file, var_names, timestep, current_value, & stdname, min_difference, min_relative_value, is_first, diff_found) use ccpp_kinds, only: kind_phys diff --git a/test/unit/python/sample_files/write_init_files/phys_vars_init_check_constituent_dim.F90 b/test/unit/python/sample_files/write_init_files/phys_vars_init_check_constituent_dim.F90 index a1235d79..e9ee6919 100644 --- a/test/unit/python/sample_files/write_init_files/phys_vars_init_check_constituent_dim.F90 +++ b/test/unit/python/sample_files/write_init_files/phys_vars_init_check_constituent_dim.F90 @@ -32,7 +32,7 @@ module phys_vars_init_check_constituent_dim integer, public, parameter :: PARAM = 2 integer, public, parameter :: READ_FROM_FILE = 3 ! Total number of physics-related variables: - integer, public, parameter :: phys_var_num = 4 + integer, public, parameter :: phys_var_num = 5 integer, public, parameter :: phys_const_num = 16 !Max length of physics-related variable standard names: @@ -46,7 +46,8 @@ module phys_vars_init_check_constituent_dim 'potential_temperature ', & 'air_pressure_at_sea_level ', & 'super_cool_cat_every_const ', & - 'super_cool_cat_with_default_every_const' /) + 'super_cool_cat_with_default_every_const', & + 'super_cool_cat_3d_every_const ' /) character(len=36), public, protected :: phys_const_stdnames(phys_const_num) = (/ & "ccpp_constituent_minimum_values ", & @@ -70,13 +71,15 @@ module phys_vars_init_check_constituent_dim 'theta ', 'pot_temp ', & 'slp ', 'sea_lev_pres ', & 'cool_cat_tend ', 'pbuf_COOL_CAT_TEND ', & - 'cool_cat_default_tend', ' ' /), (/2, phys_var_num/)) + 'cool_cat_default_tend', ' ', & + 'cool_cat_3d ', ' ' /), (/2, phys_var_num/)) ! Array indicating whether or not variable is protected: logical, public, protected :: protected_vars(phys_var_num)= (/ & .false., & .false., & .false., & + .false., & .false. /) ! Variable state (UNINITIALIZED, INTIIALIZED, PARAM or READ_FROM_FILE): @@ -84,6 +87,7 @@ module phys_vars_init_check_constituent_dim UNINITIALIZED, & UNINITIALIZED, & UNINITIALIZED, & + UNINITIALIZED, & UNINITIALIZED /) diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_4D.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_4D.F90 index d92ff84b..919aab86 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_4D.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_4D.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -235,7 +235,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -312,6 +312,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -364,7 +365,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_bvd.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_bvd.F90 index 3137ab8a..3b26e5d9 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_bvd.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_bvd.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -150,7 +150,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia call read_field(file, 'potential_temperature', input_var_names(:,name_idx), 'lev', timestep, theta) case ('air_pressure_at_sea_level') - call endrun('Cannot read slp from file'//', slp has unsupported dimension, band_number (dimension 2).') + call read_indexed_dimensioned_field(file, 'air_pressure_at_sea_level', input_var_names(:,name_idx), timestep, slp) case ('band_number') call endrun('Cannot read band_no from file'//', band_no has no horizontal dimension; band_no is a protected variable') @@ -235,7 +235,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -312,6 +312,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -364,7 +365,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_cnst.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_cnst.F90 index c9d8c9c5..5ed77ebe 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_cnst.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_cnst.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -232,7 +232,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -309,6 +309,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -361,7 +362,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_constituent_dim.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_constituent_dim.F90 index 8e0c4375..b647f271 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_constituent_dim.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_constituent_dim.F90 @@ -33,14 +33,14 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper use phys_vars_init_check_constituent_dim, 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_constituent_dim, only: cool_cat_for_each_const, cool_default_cat_for_each_const, slp, theta + use physics_types_simple_constituent_dim, only: cool_cat_3d_for_each_const, cool_cat_for_each_const, cool_default_cat_for_each_const, slp, theta ! Dummy arguments type(file_desc_t), intent(inout) :: file @@ -160,6 +160,10 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia call read_constituent_dimensioned_field(const_props, file, 'super_cool_cat_with_default_every_const', & input_var_names(:,name_idx), timestep, cool_default_cat_for_each_const, error_on_not_found=.false.) + case ('super_cool_cat_3d_every_const') + call read_constituent_dimensioned_field(const_props, file, 'super_cool_cat_3d_every_const', input_var_names(:,name_idx), & + 'lev', timestep, cool_cat_3d_for_each_const, error_on_not_found=.false.) + end select !read variables end select !special indices @@ -240,7 +244,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -252,7 +256,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, 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_constituent_dim, only: phys_var_num, phys_var_stdnames, input_var_names, std_name_len - use physics_types_simple_constituent_dim, only: cool_cat_for_each_const, theta + use physics_types_simple_constituent_dim, only: cool_cat_3d_for_each_const, cool_cat_for_each_const, theta ! Dummy arguments character(len=SHR_KIND_CL), intent(in) :: file_name @@ -317,6 +321,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -354,6 +359,14 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, call check_field(file, input_var_names(:,name_idx), 'lev', timestep, theta, 'potential_temperature', min_difference, & min_relative_value, is_first, diff_found) + case ('super_cool_cat_every_const') + call check_constituent_dimensioned_field(const_props, file, 'super_cool_cat_every_const', input_var_names(:,name_idx), timestep, & + cool_cat_for_each_const, min_difference, min_relative_value, is_first, diff_found) + + case ('super_cool_cat_3d_every_const') + call check_constituent_dimensioned_field(const_props, file, 'super_cool_cat_3d_every_const', input_var_names(:,name_idx), 'lev', & + timestep, cool_cat_3d_for_each_const, min_difference, min_relative_value, is_first, diff_found) + end select !check variables if (diff_found) then overall_diff_found = .true. @@ -369,7 +382,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_ddt.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_ddt.F90 index b3d0ca07..e8df9a24 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_ddt.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_ddt.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -232,7 +232,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -309,6 +309,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -361,7 +362,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_ddt2.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_ddt2.F90 index 00aa313f..7b86f12b 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_ddt2.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_ddt2.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -232,7 +232,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -309,6 +309,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -361,7 +362,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_ddt_array.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_ddt_array.F90 index d22a8f18..e52f262d 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_ddt_array.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_ddt_array.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -232,7 +232,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -309,6 +309,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -361,7 +362,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_host_var.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_host_var.F90 index 05cc3104..dc909251 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_host_var.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_host_var.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -229,7 +229,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -305,6 +305,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -353,7 +354,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_initial_value.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_initial_value.F90 index 8b7cf12f..042e32ae 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_initial_value.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_initial_value.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -232,7 +232,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -309,6 +309,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -361,7 +362,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_mf.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_mf.F90 index 0b0af8bd..e75434b0 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_mf.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_mf.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -233,7 +233,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -310,6 +310,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -362,7 +363,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_no_horiz.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_no_horiz.F90 index b993b3db..3bf1f15e 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_no_horiz.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_no_horiz.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -232,7 +232,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -309,6 +309,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -361,7 +362,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_noreq.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_noreq.F90 index 382c3129..99b0d3f1 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_noreq.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_noreq.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -225,7 +225,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -301,6 +301,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -349,7 +350,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_param.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_param.F90 index f9a7a1ab..4e66af18 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_param.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_param.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -235,7 +235,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -312,6 +312,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -364,7 +365,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_protect.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_protect.F90 index 37c85010..32c1dc37 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_protect.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_protect.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -232,7 +232,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -309,6 +309,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -361,7 +362,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_scalar.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_scalar.F90 index 1b338728..9257ca98 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_scalar.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_scalar.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -232,7 +232,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -309,6 +309,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -361,7 +362,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/physics_inputs_simple.F90 b/test/unit/python/sample_files/write_init_files/physics_inputs_simple.F90 index 2f31c548..6865977b 100644 --- a/test/unit/python/sample_files/write_init_files/physics_inputs_simple.F90 +++ b/test/unit/python/sample_files/write_init_files/physics_inputs_simple.F90 @@ -33,7 +33,7 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia use spmd_utils, only: masterproc use shr_kind_mod, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX use physics_data, only: read_field, find_input_name_idx, no_exist_idx, init_mark_idx, prot_no_init_idx, const_idx - use physics_data, only: read_constituent_dimensioned_field + use physics_data, only: read_constituent_dimensioned_field, read_indexed_dimensioned_field use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use ccpp_kinds, only: kind_phys use string_utils, only: to_lower, to_upper @@ -232,7 +232,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 physics_data, only: flush_check_field_verbose + use physics_data, only: check_constituent_dimensioned_field, flush_check_field_verbose use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array, cam_model_const_properties use cam_constituents, only: const_get_index use ccpp_kinds, only: kind_phys @@ -309,6 +309,7 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, end if allocate(file) call cam_pio_openfile(file, ncdata_check_loc, pio_nowrite, log_info=.false.) + const_props => cam_model_const_properties() ! Loop over CCPP physics/chemistry suites: do suite_idx = 1, size(suite_names, 1) @@ -368,7 +369,6 @@ subroutine physics_check_data(file_name, suite_names, timestep, min_difference, ! Check constituent variables field_data_ptr => cam_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: diff --git a/test/unit/python/sample_files/write_init_files/simple_reg_constituent_dim.xml b/test/unit/python/sample_files/write_init_files/simple_reg_constituent_dim.xml index 2563d7f6..302d84c4 100644 --- a/test/unit/python/sample_files/write_init_files/simple_reg_constituent_dim.xml +++ b/test/unit/python/sample_files/write_init_files/simple_reg_constituent_dim.xml @@ -32,5 +32,14 @@ 2.33_kind_phys cool_cat_default_tend + + + The coolest imaginable vertically-resolved value per constituent + horizontal_dimension vertical_layer_dimension number_of_ccpp_constituents + 0.0_kind_phys + cool_cat_3d + diff --git a/test/unit/python/sample_files/write_init_files/temp_adjust_constituent_dim.F90 b/test/unit/python/sample_files/write_init_files/temp_adjust_constituent_dim.F90 index 9dd3d099..9090a49c 100644 --- a/test/unit/python/sample_files/write_init_files/temp_adjust_constituent_dim.F90 +++ b/test/unit/python/sample_files/write_init_files/temp_adjust_constituent_dim.F90 @@ -19,7 +19,7 @@ MODULE temp_adjust !! SUBROUTINE temp_adjust_run(nbox, lev, temp_layer, & slp, cool_cat_for_each_const, cool_cat_default_for_each_const, & - timestep, errmsg, errflg) + cool_cat_3d_for_each_const, timestep, errmsg, errflg) !---------------------------------------------------------------- IMPLICIT NONE !---------------------------------------------------------------- @@ -29,6 +29,7 @@ SUBROUTINE temp_adjust_run(nbox, lev, temp_layer, & real(kind_phys), intent(in) :: slp(:) real(kind_phys), intent(inout) :: cool_cat_for_each_const(:,:) real(kind_phys), intent(in) :: cool_cat_default_for_each_const(:,:) + real(kind_phys), intent(inout) :: cool_cat_3d_for_each_const(:,:,:) real(kind_phys), intent(in) :: timestep character(len=512), intent(out) :: errmsg integer, intent(out) :: errflg diff --git a/test/unit/python/sample_files/write_init_files/temp_adjust_constituent_dim.meta b/test/unit/python/sample_files/write_init_files/temp_adjust_constituent_dim.meta index 09f53138..9b0f72e2 100644 --- a/test/unit/python/sample_files/write_init_files/temp_adjust_constituent_dim.meta +++ b/test/unit/python/sample_files/write_init_files/temp_adjust_constituent_dim.meta @@ -44,6 +44,13 @@ type = real kind = kind_phys intent = in +[ cool_cat_3d_for_each_const ] + standard_name = super_cool_cat_3d_every_const + units = kg kg-1 + dimensions = (horizontal_loop_extent, vertical_layer_dimension, number_of_ccpp_constituents) + type = real + kind = kind_phys + intent = inout [ timestep ] standard_name = timestep_for_physics long_name = time step diff --git a/test/unit/python/test_write_init_files.py b/test/unit/python/test_write_init_files.py index cc563747..a80332d2 100644 --- a/test/unit/python/test_write_init_files.py +++ b/test/unit/python/test_write_init_files.py @@ -1256,8 +1256,8 @@ def test_bad_vertical_dimension(self): could be called from "read_field" has two dimensions but the second is not a vertical dimension (which read_field can't handle) and is not the number of constituents, - and exits with both the correct return - message, and with no Fortran files generated. + and generates a "read_indexed_dimensioned_field" call for it + (numbered per-slice file variables) instead of a "read_field" call. """ # Setup registry inputs: