Skip to content

Commit

Permalink
Merge pull request #226 from mwaxmonsky/constituent_default
Browse files Browse the repository at this point in the history
Initial attempt of setting default constituent value.
  • Loading branch information
mwaxmonsky committed Aug 23, 2023
2 parents b00016a + 3381e15 commit 55b850f
Show file tree
Hide file tree
Showing 17 changed files with 719 additions and 80 deletions.
2 changes: 1 addition & 1 deletion Externals_CAM.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
local_path = ccpp_framework
protocol = git
repo_url = https://github.com/peverwhee/ccpp-framework
tag = CPF_0.2.043
tag = CPF_0.2.045
required = True

[cosp2]
Expand Down
41 changes: 38 additions & 3 deletions src/data/write_init_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -819,10 +819,12 @@ 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_ccpp_cap", ["ccpp_physics_suite_variables", "cam_constituents_array", "cam_model_const_properties"]],
["ccpp_kinds", ["kind_phys"]],
[phys_check_fname_str, ["phys_var_stdnames",
"input_var_names", "std_name_len"]]]
"input_var_names", "std_name_len"]],
["ccpp_constituent_prop_mod", ["ccpp_constituent_prop_ptr_t"]],
["cam_logfile", ["iulog"]]]

# Add in host model data use statements
use_stmts.extend(host_imports)
Expand Down Expand Up @@ -860,6 +862,14 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
outfile.write("character(len=2) :: sep2 !String separator used to print err messages", 2)
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.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("integer :: constituent_errflg", 2)
outfile.write("character(len=512) :: constituent_errmsg", 2)
outfile.write("logical :: constituent_has_default", 2)
outfile.blank_line()
outfile.comment("Logical to default optional argument to False:", 2)
outfile.write("logical :: use_init_variables", 2)
Expand Down Expand Up @@ -949,8 +959,33 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
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.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.)", 6)
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)", 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 ', 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 ', 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.blank_line()

# start default case steps:
outfile.write("case default", 5)
Expand Down
6 changes: 3 additions & 3 deletions src/dynamics/se/dyn_comp.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1843,9 +1843,9 @@ subroutine read_inidat(dyn_in)
call mark_as_initialized("reciprocal_of_pressure_thickness")
call mark_as_initialized("inverse_exner_function_wrt_surface_pressure")
call mark_as_initialized("lagrangian_tendency_of_air_pressure")
call mark_as_initialized("total_tendency_of_air_temperature")
call mark_as_initialized("total_tendency_of_x_wind")
call mark_as_initialized("total_tendency_of_y_wind")
call mark_as_initialized("tendency_of_air_temperature_due_to_model_physics")
call mark_as_initialized("tendency_of_x_wind_due_to_model_physics")
call mark_as_initialized("tendency_of_y_wind_due_to_model_physics")

end subroutine read_inidat

Expand Down
106 changes: 77 additions & 29 deletions src/physics/utils/physics_data.F90
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module physics_data

use ccpp_kinds, only: kind_phys
use shr_kind_mod, only: cl=>shr_kind_cl

implicit none
private
Expand Down Expand Up @@ -135,7 +136,7 @@ function arr2str(name_array)
end function arr2str


subroutine read_field_2d(file, std_name, var_names, timestep, buffer, mark_as_read)
subroutine read_field_2d(file, std_name, var_names, timestep, buffer, mark_as_read, error_on_not_found, var_found)
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
Expand All @@ -155,49 +156,72 @@ subroutine read_field_2d(file, std_name, var_names, timestep, buffer, mark_as_re
character(len=*), intent(in) :: var_names(:) ! var name on file
integer, intent(in) :: timestep
real(kind_phys), intent(inout) :: buffer(:)
logical, optional, intent(in) :: mark_as_read
logical, optional, intent(in) :: mark_as_read ! Mark field as read if found
logical, optional, intent(in) :: error_on_not_found ! Flag to error and exit if not found
logical, optional, intent(out) :: var_found ! Flag to mark variable was found
! Local variables
logical :: mark_as_read_local
logical :: var_found
logical :: error_on_not_found_local
logical :: var_found_local
character(len=std_name_len) :: found_name
type(var_desc_t) :: vardesc
character(len=*), parameter :: subname = 'read_field_2d: '
character(len=cl) :: strerr

if (present(mark_as_read)) then
mark_as_read_local = mark_as_read
else
mark_as_read_local = .true.
end if

call cam_pio_find_var(file, var_names, found_name, vardesc, var_found)
if (.not. var_found) then
call cam_pio_find_var(file, [std_name], found_name, vardesc, var_found)
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

if (var_found) then
var_found_local = .false.
call cam_pio_find_var(file, var_names, found_name, vardesc, var_found_local)
if (.not. var_found_local) then
call cam_pio_find_var(file, [std_name], found_name, vardesc, var_found_local)
end if

if (var_found_local) then
if (masterproc) then
write(iulog, *) 'Reading input field, ', trim(found_name)
call shr_sys_flush(iulog)
end if
call cam_read_field(found_name, file, buffer, var_found, &
call cam_read_field(found_name, file, buffer, var_found_local, &
timelevel=timestep)

if (mark_as_read_local) then
call mark_as_read_from_file(std_name)
end if

if (var_found_local) then
call shr_assert_in_domain(buffer, is_nan=.false., &
varname=trim(found_name), &
msg=subname//'NaN found in '//trim(found_name))
else
write(strerr,*) subname//'Unable to properly check the found variable "', trim(found_name), '" in the IC file. &
&Please double-check if the variable exists in the file and that the file is not corrupted or damaged.'
call endrun(strerr)
end if
else if (.not. error_on_not_found_local) then
if (masterproc) then
write(iulog, *) trim(std_name), ' not found, also looked for: ', trim(arr2str(var_names))
call shr_sys_flush(iulog)
end if
else
call endrun(subname//'No variable found in '//arr2str(var_names))
end if
if (var_found) then
call shr_assert_in_domain(buffer, is_nan=.false., &
varname=trim(found_name), &
msg=subname//'NaN found in '//trim(found_name))
else
call endrun(subname//'Mismatch variable found in '//arr2str(var_names))
end if
if (present(var_found)) then
var_found = var_found_local
end if
end subroutine read_field_2d

subroutine read_field_3d(file, std_name, var_names, vcoord_name, &
timestep, buffer, mark_as_read)
timestep, buffer, mark_as_read, error_on_not_found, var_found)
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
Expand All @@ -219,27 +243,39 @@ subroutine read_field_3d(file, std_name, var_names, vcoord_name, &
character(len=*), intent(in) :: vcoord_name
integer, intent(in) :: timestep
real(kind_phys), intent(inout) :: buffer(:,:)
logical, optional, intent(in) :: mark_as_read
logical, optional, intent(in) :: mark_as_read ! Mark field as read if found
logical, optional, intent(in) :: error_on_not_found ! Flag to error and exit if not found
logical, optional, intent(out) :: var_found ! Flag to mark variable was found
! Local variables
logical :: mark_as_read_local
logical :: var_found
logical :: error_on_not_found_local
logical :: var_found_local
integer :: num_levs
character(len=std_name_len) :: found_name
type(var_desc_t) :: vardesc
character(len=*), parameter :: subname = 'read_field_3d: '
character(len=cl) :: strerr

if (present(mark_as_read)) then
mark_as_read_local = mark_as_read
else
mark_as_read_local = .true.
end if

call cam_pio_find_var(file, var_names, found_name, vardesc, var_found)
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

var_found_local = .false.
call cam_pio_find_var(file, var_names, found_name, vardesc, var_found_local)

if (.not. var_found) then
call cam_pio_find_var(file, [std_name], found_name, vardesc, var_found)
if (.not. var_found_local) then
call cam_pio_find_var(file, [std_name], found_name, vardesc, var_found_local)
end if
if (var_found) then

if (var_found_local) then
if (trim(vcoord_name) == 'lev') then
num_levs = pver
else if (trim(vcoord_name) == 'ilev') then
Expand All @@ -251,21 +287,33 @@ subroutine read_field_3d(file, std_name, var_names, vcoord_name, &
write(iulog, *) 'Reading input field, ', trim(found_name)
call shr_sys_flush(iulog)
end if
call cam_read_field(found_name, file, buffer, var_found, &
call cam_read_field(found_name, file, buffer, var_found_local, &
timelevel=timestep, dim3name=trim(vcoord_name), &
dim3_bnds=(/1, num_levs/))

if (mark_as_read_local) then
call mark_as_read_from_file(std_name)
end if

if (var_found_local) then
call shr_assert_in_domain(buffer, is_nan=.false., &
varname=trim(found_name), &
msg=subname//'NaN found in '//trim(found_name))
else
write(strerr,*) subname//'Unable to properly check the found variable "', trim(found_name), '" in the IC file. &
&Please double-check if the variable exists in the file and that the file is not corrupted or damaged.'
call endrun(strerr)
end if
else if (.not. error_on_not_found_local) then
if (masterproc) then
write(iulog, *) trim(std_name), ' not found, also looked for: ', trim(arr2str(var_names))
call shr_sys_flush(iulog)
end if
else
call endrun(subname//'No variable found in '//arr2str(var_names))
end if
if (var_found) then
call shr_assert_in_domain(buffer, is_nan=.false., &
varname=trim(found_name), &
msg=subname//'NaN found in '//trim(found_name))
else
call endrun(subname//'Mismatch variable found in '//found_name)
if (present(var_found)) then
var_found = var_found_local
end if
end subroutine read_field_3d

Expand Down
63 changes: 53 additions & 10 deletions test/unit/sample_files/write_init_files/physics_inputs_4D.F90
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,18 @@ module physics_inputs_4D
CONTAINS

subroutine physics_read_data(file, suite_names, timestep, read_initialized_variables)
use pio, only: file_desc_t
use cam_abortutils, only: endrun
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
use physics_data, only: init_mark_idx, prot_no_init_idx, const_idx
use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array
use ccpp_kinds, only: kind_phys
use phys_vars_init_check_4D, only: phys_var_stdnames, input_var_names, std_name_len
use physics_types_4D, only: slp, theta
use pio, only: file_desc_t
use cam_abortutils, only: endrun
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
use physics_data, only: init_mark_idx, prot_no_init_idx, const_idx
use cam_ccpp_cap, only: ccpp_physics_suite_variables, cam_constituents_array
use cam_ccpp_cap, only: cam_model_const_properties
use ccpp_kinds, only: kind_phys
use phys_vars_init_check_4D, only: phys_var_stdnames, input_var_names, std_name_len
use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t
use cam_logfile, only: iulog
use physics_types_4D, only: slp, theta

! Dummy arguments
type(file_desc_t), intent(inout) :: file
Expand All @@ -64,6 +67,15 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia
character(len=2) :: sep2 !String separator used to print err messages
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

! 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
integer :: constituent_errflg
character(len=512) :: constituent_errmsg
logical :: constituent_has_default

! Logical to default optional argument to False:
logical :: use_init_variables
Expand Down Expand Up @@ -130,10 +142,41 @@ subroutine physics_read_data(file, suite_names, timestep, read_initialized_varia
! 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()
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.)
field_data_ptr(:,:,constituent_idx), mark_as_read=.false., &
error_on_not_found=.false., var_found=var_found)
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 ', 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 ', ccpp_required_data(req_idx), &
' default value not configured. Setting to 0.'
end if
end if
end if

case default

! Read variable from IC file:
Expand Down
Loading

0 comments on commit 55b850f

Please sign in to comment.