Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions fms2_io/blackboxio.F90
Original file line number Diff line number Diff line change
Expand Up @@ -561,13 +561,14 @@ end subroutine save_domain_restart_wrap
!> @brief Loop through registered restart variables and read them from
!! a netcdf file.
subroutine restore_domain_state_wrap(fileobj, unlim_dim_level, directory, timestamp, &
filename)
filename, ignore_checksum)

type(FmsNetcdfDomainFile_t), intent(in), target :: fileobj !< File object.
integer, intent(in), optional :: unlim_dim_level !< Unlimited dimension level.
character(len=*), intent(in), optional :: directory !< Directory to write restart file to.
character(len=*), intent(in), optional :: timestamp !< Model time.
character(len=*), intent(in), optional :: filename !< New name for the file.
logical, intent(in), optional :: ignore_checksum !< Checksum data integrity flag.

character(len=256) :: new_name
type(FmsNetcdfDomainFile_t), target :: new_fileobj
Expand All @@ -583,7 +584,7 @@ subroutine restore_domain_state_wrap(fileobj, unlim_dim_level, directory, timest
p => new_fileobj
close_new_file = .true.
endif
call restore_domain_state(p, unlim_dim_level)
call restore_domain_state(p, unlim_dim_level, ignore_checksum=ignore_checksum)
if (close_new_file) then
call close_domain_file(p)
endif
Expand Down
73 changes: 42 additions & 31 deletions fms2_io/fms_netcdf_domain_io.F90
Original file line number Diff line number Diff line change
Expand Up @@ -627,16 +627,21 @@ end subroutine save_domain_restart

!> @brief Loop through registered restart variables and read them from
!! a netcdf file.
subroutine restore_domain_state(fileobj, unlim_dim_level)
subroutine restore_domain_state(fileobj, unlim_dim_level, ignore_checksum)

type(FmsNetcdfDomainFile_t), intent(inout) :: fileobj !< File object.
integer, intent(in), optional :: unlim_dim_level !< Unlimited dimension level.
logical, intent(in), optional :: ignore_checksum !< Checksum data integrity flag.

integer :: i
character(len=32) :: chksum_in_file
character(len=32) :: chksum
logical :: chksum_ignore = .FALSE. ! local variable for data integrity checks
! default: .FALSE. - checks enabled
Comment thread
bensonr marked this conversation as resolved.
Outdated
logical :: is_decomposed

if (PRESENT(ignore_checksum)) chksum_ignore = ignore_checksum

if (.not. fileobj%is_restart) then
call error("file "//trim(fileobj%path)//" is not a restart file. You must set is_restart=.true. in your open_file call.")
endif
Expand All @@ -650,46 +655,52 @@ subroutine restore_domain_state(fileobj, unlim_dim_level)
elseif (associated(fileobj%restart_vars(i)%data2d)) then
call domain_read_2d(fileobj, fileobj%restart_vars(i)%varname, &
fileobj%restart_vars(i)%data2d, unlim_dim_level=unlim_dim_level)
chksum = compute_global_checksum(fileobj, fileobj%restart_vars(i)%varname, &
fileobj%restart_vars(i)%data2d, is_decomposed)
if (variable_att_exists(fileobj, fileobj%restart_vars(i)%varname, "checksum") .and. &
is_decomposed) then
call get_variable_attribute(fileobj, fileobj%restart_vars(i)%varname, &
"checksum", chksum_in_file)
if (.not. string_compare(trim(adjustl(chksum_in_file)), trim(adjustl(chksum)))) then
call error("The checksum in the file:"//trim(fileobj%path)//" and variable:"//trim(fileobj%restart_vars(i)%varname)//&
&" does not match the checksum calculated from the data. file:"//trim(adjustl(chksum_in_file))//&
&" from data:"//trim(adjustl(chksum)))
if (.not.chksum_ignore) then
chksum = compute_global_checksum(fileobj, fileobj%restart_vars(i)%varname, &
fileobj%restart_vars(i)%data2d, is_decomposed)
if (variable_att_exists(fileobj, fileobj%restart_vars(i)%varname, "checksum") .and. &
is_decomposed) then
call get_variable_attribute(fileobj, fileobj%restart_vars(i)%varname, &
"checksum", chksum_in_file)
if (.not. string_compare(trim(adjustl(chksum_in_file)), trim(adjustl(chksum)))) then
call error("The checksum in the file:"//trim(fileobj%path)//" and variable:"//trim(fileobj%restart_vars(i)%varname)//&
&" does not match the checksum calculated from the data. file:"//trim(adjustl(chksum_in_file))//&
&" from data:"//trim(adjustl(chksum)))
endif
endif
endif
elseif (associated(fileobj%restart_vars(i)%data3d)) then
call domain_read_3d(fileobj, fileobj%restart_vars(i)%varname, &
fileobj%restart_vars(i)%data3d, unlim_dim_level=unlim_dim_level)
chksum = compute_global_checksum(fileobj, fileobj%restart_vars(i)%varname, &
fileobj%restart_vars(i)%data3d, is_decomposed)
if (variable_att_exists(fileobj, fileobj%restart_vars(i)%varname, "checksum") .and. &
is_decomposed) then
call get_variable_attribute(fileobj, fileobj%restart_vars(i)%varname, &
"checksum", chksum_in_file(1:len(chksum_in_file)))
if (.not. string_compare(trim(adjustl(chksum_in_file)), trim(adjustl(chksum)))) then
call error("The checksum in the file:"//trim(fileobj%path)//" and variable:"//trim(fileobj%restart_vars(i)%varname)//&
&" does not match the checksum calculated from the data. file:"//trim(adjustl(chksum_in_file))//&
&" from data:"//trim(adjustl(chksum)))
if (.not.chksum_ignore) then
chksum = compute_global_checksum(fileobj, fileobj%restart_vars(i)%varname, &
fileobj%restart_vars(i)%data3d, is_decomposed)
if (variable_att_exists(fileobj, fileobj%restart_vars(i)%varname, "checksum") .and. &
is_decomposed) then
call get_variable_attribute(fileobj, fileobj%restart_vars(i)%varname, &
"checksum", chksum_in_file(1:len(chksum_in_file)))
if (.not. string_compare(trim(adjustl(chksum_in_file)), trim(adjustl(chksum)))) then
call error("The checksum in the file:"//trim(fileobj%path)//" and variable:"//trim(fileobj%restart_vars(i)%varname)//&
&" does not match the checksum calculated from the data. file:"//trim(adjustl(chksum_in_file))//&
&" from data:"//trim(adjustl(chksum)))
endif
endif
endif
elseif (associated(fileobj%restart_vars(i)%data4d)) then
call domain_read_4d(fileobj, fileobj%restart_vars(i)%varname, &
fileobj%restart_vars(i)%data4d, unlim_dim_level=unlim_dim_level)
chksum = compute_global_checksum(fileobj, fileobj%restart_vars(i)%varname, &
fileobj%restart_vars(i)%data4d, is_decomposed)
if (variable_att_exists(fileobj, fileobj%restart_vars(i)%varname, "checksum") .and. &
is_decomposed) then
call get_variable_attribute(fileobj, fileobj%restart_vars(i)%varname, &
"checksum", chksum_in_file)
if (.not. string_compare(trim(adjustl(chksum_in_file)), trim(adjustl(chksum)))) then
call error("The checksum in the file:"//trim(fileobj%path)//" and variable:"//trim(fileobj%restart_vars(i)%varname)//&
&" does not match the checksum calculated from the data. file:"//trim(adjustl(chksum_in_file))//&
&" from data:"//trim(adjustl(chksum)))
if (.not.chksum_ignore) then
chksum = compute_global_checksum(fileobj, fileobj%restart_vars(i)%varname, &
fileobj%restart_vars(i)%data4d, is_decomposed)
if (variable_att_exists(fileobj, fileobj%restart_vars(i)%varname, "checksum") .and. &
is_decomposed) then
call get_variable_attribute(fileobj, fileobj%restart_vars(i)%varname, &
"checksum", chksum_in_file)
if (.not. string_compare(trim(adjustl(chksum_in_file)), trim(adjustl(chksum)))) then
call error("The checksum in the file:"//trim(fileobj%path)//" and variable:"//trim(fileobj%restart_vars(i)%varname)//&
&" does not match the checksum calculated from the data. file:"//trim(adjustl(chksum_in_file))//&
&" from data:"//trim(adjustl(chksum)))
endif
endif
endif
else
Expand Down
28 changes: 18 additions & 10 deletions fms2_io/include/scatter_data_bc.inc
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
!> @ingroup fms2_io

!< Root pe reads the data in the netcdf file and scatters it to the other pes
subroutine scatter_data_bc_2d(fileobj, varname, vdata, bc_info, unlim_dim_level)
subroutine scatter_data_bc_2d(fileobj, varname, vdata, bc_info, unlim_dim_level, ignore_checksum)
class(FmsNetcdfFile_t), intent(inout) :: fileobj !< Fms2io netcdf fileobj
character(len=*), intent(in) :: varname !< Variable name.
class(*), dimension(:,:), intent(inout) :: vdata !< scattered data
type(bc_information), intent(inout) :: bc_info !< information about the boundary condition variable
integer, intent(in), optional :: unlim_dim_level !< Unlimited dimension
!! level.
integer, intent(in), optional :: unlim_dim_level !< Unlimited dimension level.
logical, intent(in), optional :: ignore_checksum !< Checksum data integrity flag.

real(kind=r8_kind), dimension(:,:), allocatable :: global_buf_r8_kind !< buffer with a data read in from file
real(kind=r8_kind), dimension(:,:), allocatable :: local_buf_r8_kind !< current pe's portion of the data
Expand All @@ -36,6 +36,8 @@ subroutine scatter_data_bc_2d(fileobj, varname, vdata, bc_info, unlim_dim_level)
integer(kind=i8_kind) :: chksum_val !< Checksum value calculated from the read data
character(len=32) :: chksum !< Cheksum value converted to a string
character(len=32) :: chksum_read !< String checksum read in from file
logical :: chksum_ignore = .FALSE. ! local variable for data integrity checks
! default: .FALSE. - checks enabled
Comment thread
bensonr marked this conversation as resolved.
Outdated

integer :: isc, iec, jsc, jec !< current PE's indices
integer :: i1, i2, j1, j2 !< current PE's indices relative to the global domain
Expand All @@ -44,6 +46,8 @@ subroutine scatter_data_bc_2d(fileobj, varname, vdata, bc_info, unlim_dim_level)
integer :: i_glob !< Size of the global domain in x
integer :: j_glob !< Size of the global domain in y

if (PRESENT(ignore_checksum)) chksum_ignore = ignore_checksum

!> Set the indices
isc = bc_info%indices(1)
iec = bc_info%indices(2)
Expand Down Expand Up @@ -76,7 +80,7 @@ subroutine scatter_data_bc_2d(fileobj, varname, vdata, bc_info, unlim_dim_level)
unlim_dim_level=unlim_dim_level, &
broadcast=.false.)
!> If the checksum exists read it and compare it with the calculated from the data that was read
if (variable_att_exists(fileobj, varname, "checksum", broadcast=.false.)) then
if (.not.chksum_ignore .and. variable_att_exists(fileobj, varname, "checksum", broadcast=.false.)) then
call get_variable_attribute(fileobj, varname, "checksum", chksum_read, broadcast=.false.)
chksum_val = mpp_chksum(global_buf_r4_kind, (/mpp_pe()/))
chksum = ""
Expand Down Expand Up @@ -124,7 +128,7 @@ subroutine scatter_data_bc_2d(fileobj, varname, vdata, bc_info, unlim_dim_level)
unlim_dim_level=unlim_dim_level, &
broadcast=.false.)
!> If the checksum exists read it and compare it with the calculated from the data that was read
if (variable_att_exists(fileobj, varname, "checksum", broadcast=.false.)) then
if (.not.chksum_ignore .and. variable_att_exists(fileobj, varname, "checksum", broadcast=.false.)) then
call get_variable_attribute(fileobj, varname, "checksum", chksum_read, broadcast=.false.)
chksum_val = mpp_chksum(global_buf_r8_kind, (/mpp_pe()/))
chksum = ""
Expand Down Expand Up @@ -168,13 +172,13 @@ subroutine scatter_data_bc_2d(fileobj, varname, vdata, bc_info, unlim_dim_level)
end subroutine scatter_data_bc_2d

!< Root pe reads the data in the netcdf file and scatters it to the other pes
subroutine scatter_data_bc_3d(fileobj, varname, vdata, bc_info, unlim_dim_level)
subroutine scatter_data_bc_3d(fileobj, varname, vdata, bc_info, unlim_dim_level, ignore_checksum)
class(FmsNetcdfFile_t), intent(inout) :: fileobj !< Fms2io netcdf fileobj
character(len=*), intent(in) :: varname !< Variable name.
class(*), dimension(:,:,:), intent(inout) :: vdata !< scattered data
type(bc_information), intent(inout) :: bc_info !< information about the boundary condition variable
integer, intent(in), optional :: unlim_dim_level !< Unlimited dimension
!! level.
integer, intent(in), optional :: unlim_dim_level !< Unlimited dimension level.
logical, intent(in), optional :: ignore_checksum !< Checksum data integrity flag.

real(kind=r8_kind), dimension(:,:,:), allocatable :: global_buf_r8_kind !< buffer with a data read in from file
real(kind=r8_kind), dimension(:,:,:), allocatable :: local_buf_r8_kind !< current pe's portion of the data
Expand All @@ -184,6 +188,8 @@ subroutine scatter_data_bc_3d(fileobj, varname, vdata, bc_info, unlim_dim_level)
integer(kind=i8_kind) :: chksum_val !< Checksum value calculated from the read data
character(len=32) :: chksum !< Cheksum value converted to a string
character(len=32) :: chksum_read !< String checksum read in from file
logical :: chksum_ignore = .FALSE. ! local variable for data integrity checks
! default: .FALSE. - checks enabled
Comment thread
bensonr marked this conversation as resolved.
Outdated

integer :: isc, iec, jsc, jec !< current PE's indices
integer :: i1, i2, j1, j2 !< current PE's indices relative to the global domain
Expand All @@ -193,6 +199,8 @@ subroutine scatter_data_bc_3d(fileobj, varname, vdata, bc_info, unlim_dim_level)
integer :: j_glob !< Size of the global domain in y
integer :: k_glob !< Size of the z axis

if (PRESENT(ignore_checksum)) chksum_ignore = ignore_checksum

!> Set the indices
isc = bc_info%indices(1)
iec = bc_info%indices(2)
Expand Down Expand Up @@ -227,7 +235,7 @@ subroutine scatter_data_bc_3d(fileobj, varname, vdata, bc_info, unlim_dim_level)
unlim_dim_level=unlim_dim_level, &
broadcast=.false.)
!> If the checksum exists read it and compare it with the calculated from the data that was read
if (variable_att_exists(fileobj, varname, "checksum", broadcast=.false.)) then
if (.not.chksum_ignore .and. variable_att_exists(fileobj, varname, "checksum", broadcast=.false.)) then
call get_variable_attribute(fileobj, varname, "checksum", chksum_read, broadcast=.false.)
chksum_val = mpp_chksum(global_buf_r4_kind, (/mpp_pe()/))
chksum = ""
Expand Down Expand Up @@ -275,7 +283,7 @@ subroutine scatter_data_bc_3d(fileobj, varname, vdata, bc_info, unlim_dim_level)
unlim_dim_level=unlim_dim_level, &
broadcast=.false.)
!> If the checksum exists read it and compare it with the calculated from the data that was read
if (variable_att_exists(fileobj, varname, "checksum", broadcast=.false.)) then
if (.not.chksum_ignore .and. variable_att_exists(fileobj, varname, "checksum", broadcast=.false.)) then
call get_variable_attribute(fileobj, varname, "checksum", chksum_read, broadcast=.false.)
chksum_val = mpp_chksum(global_buf_r8_kind, (/mpp_pe()/))
chksum = ""
Expand Down
10 changes: 7 additions & 3 deletions fms2_io/netcdf_io.F90
Original file line number Diff line number Diff line change
Expand Up @@ -2172,10 +2172,12 @@ end subroutine set_fileobj_time_name

!> @brief Loop through the registered restart variables (including regional
!! variables) and read them from the netcdf file
subroutine read_restart_bc(fileobj, unlim_dim_level)
subroutine read_restart_bc(fileobj, unlim_dim_level, ignore_checksum)
class(FmsNetcdfFile_t), intent(inout) :: fileobj !< File object
integer, intent(in), optional :: unlim_dim_level !< Unlimited dimension
!! level.
logical, intent(in), optional :: ignore_checksum !< Checksum data integrity flag.

integer :: i !< No description

if (.not. fileobj%is_restart) then
Expand All @@ -2190,11 +2192,13 @@ subroutine read_restart_bc(fileobj, unlim_dim_level)
if (associated(fileobj%restart_vars(i)%data2d)) then
call scatter_data_bc (fileobj, fileobj%restart_vars(i)%varname, &
fileobj%restart_vars(i)%data2d, &
fileobj%restart_vars(i)%bc_info)
fileobj%restart_vars(i)%bc_info, &
ignore_checksum=ignore_checksum)
else if (associated(fileobj%restart_vars(i)%data3d)) then
call scatter_data_bc (fileobj, fileobj%restart_vars(i)%varname, &
fileobj%restart_vars(i)%data3d, &
fileobj%restart_vars(i)%bc_info)
fileobj%restart_vars(i)%bc_info, &
ignore_checksum=ignore_checksum)
endif
end do

Expand Down
22 changes: 19 additions & 3 deletions test_fms/fms2_io/test_atmosphere_io.F90
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ program test_atmosphere_io
character(len=256) :: att
character(len=6), dimension(4) :: names
character(len=8) :: timestamp
logical :: ignore_checksum = .false.
logical :: bad_checksum = .false.

namelist /test_atmosphere_io_nml/ bad_checksum, ignore_checksum

!Initialize.
call init(test_params, ntiles)
Expand All @@ -93,6 +97,8 @@ program test_atmosphere_io
call random_seed()
call fms2_io_init()

read(input_nml_file, nml=test_atmosphere_io_nml)

if (test_params%debug) then
if (mpp_pe() .eq. 0) then
write(error_unit,'(/a)') &
Expand Down Expand Up @@ -346,6 +352,12 @@ program test_atmosphere_io
var10_chksum = mpp_chksum(var10, pelist=(/mpp_pe()/))
!var11_chksum = mpp_chksum(var11(isc-isd+1:isc-isd+1+nx, jsc-jsd+1:jsc-jsd+1+ny, :), pelist=(/mpp_pe()/))

!replace var6 checksum with an incorrect checksum
if (bad_checksum) then
var6_chksum = 101010101
call register_variable_attribute(fileobj , "var6", "checksum", "101010101", str_len = 9)
call register_variable_attribute(fileobjv, "var6", "checksum", "101010101", str_len = 9)
endif
!Close the file.
call close_file(fileobj)
call mpi_barrier(mpi_comm_world, err)
Expand Down Expand Up @@ -474,7 +486,7 @@ program test_atmosphere_io
deallocate(dim_sizes)

!Read in the restart data.
call read_restart(fileobj, unlim_dim_level=nt)
call read_restart(fileobj, unlim_dim_level=nt, ignore_checksum = ignore_checksum )


chksum = mpp_chksum(var5, pelist=(/mpp_pe()/))
Expand All @@ -486,7 +498,11 @@ program test_atmosphere_io

chksum = mpp_chksum(var6, pelist=(/mpp_pe()/))
if (chksum .ne. var6_chksum) then
call mpp_error(fatal, "checksum for var 6 does not match.")
if (ignore_checksum) then
call mpp_error(warning, "checksum for var 6 does not match.")
else
call mpp_error(fatal, "checksum for var 6 does not match.")
endif
else
call mpp_error(warning, "checksum for var 6 does match.")
endif
Expand All @@ -513,7 +529,7 @@ program test_atmosphere_io
var6p = 0.
var7p = 0.
var8p = 0.
call read_new_restart(fileobjv, timestamp=timestamp)
call read_new_restart(fileobjv, timestamp=timestamp, ignore_checksum=ignore_checksum)

!Close the file.
call close_file(fileobj)
Expand Down
Loading