diff --git a/fms2_io/blackboxio.F90 b/fms2_io/blackboxio.F90 index dbe1cb4cb7..76c8740eca 100644 --- a/fms2_io/blackboxio.F90 +++ b/fms2_io/blackboxio.F90 @@ -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 @@ -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 diff --git a/fms2_io/fms_netcdf_domain_io.F90 b/fms2_io/fms_netcdf_domain_io.F90 index e39cd9028e..b15abbd5eb 100644 --- a/fms2_io/fms_netcdf_domain_io.F90 +++ b/fms2_io/fms_netcdf_domain_io.F90 @@ -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 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 @@ -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 diff --git a/fms2_io/include/scatter_data_bc.inc b/fms2_io/include/scatter_data_bc.inc index b1c63320e6..ace4c68edd 100644 --- a/fms2_io/include/scatter_data_bc.inc +++ b/fms2_io/include/scatter_data_bc.inc @@ -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 @@ -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 integer :: isc, iec, jsc, jec !< current PE's indices integer :: i1, i2, j1, j2 !< current PE's indices relative to the global domain @@ -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) @@ -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 = "" @@ -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 = "" @@ -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 @@ -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 integer :: isc, iec, jsc, jec !< current PE's indices integer :: i1, i2, j1, j2 !< current PE's indices relative to the global domain @@ -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) @@ -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 = "" @@ -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 = "" diff --git a/fms2_io/netcdf_io.F90 b/fms2_io/netcdf_io.F90 index bf028d7819..5a33f151d9 100644 --- a/fms2_io/netcdf_io.F90 +++ b/fms2_io/netcdf_io.F90 @@ -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 @@ -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 diff --git a/test_fms/fms2_io/test_atmosphere_io.F90 b/test_fms/fms2_io/test_atmosphere_io.F90 index 48b7c9e00b..dcf6438a9f 100644 --- a/test_fms/fms2_io/test_atmosphere_io.F90 +++ b/test_fms/fms2_io/test_atmosphere_io.F90 @@ -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) @@ -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)') & @@ -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) @@ -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()/)) @@ -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 @@ -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) diff --git a/test_fms/fms2_io/test_atmosphere_io.sh b/test_fms/fms2_io/test_atmosphere_io.sh index bc4018787a..ffa5d8b6f1 100755 --- a/test_fms/fms2_io/test_atmosphere_io.sh +++ b/test_fms/fms2_io/test_atmosphere_io.sh @@ -26,13 +26,28 @@ . ../test_common.sh [ -d atmosphere-output ] && rm -r atmosphere-output + +# run test 1 - standard test mkdir atmosphere-output cd atmosphere-output +touch input.nml +run_test ../test_atmosphere_io 6 +cd .. && rm -r atmosphere-output -# make an input.nml for mpp_init to read -printf "EOF\n&dummy\nEOF" | cat > input.nml +# run test 2 - test for bad checksum (should fail) +mkdir atmosphere-output +cd atmosphere-output +printf "&test_atmosphere_io_nml\n bad_checksum=.true.\n /" | cat > input.nml +if run_test ../test_atmosphere_io 6; then + echo " test was supposed to fail and didn't " + exit -99 +fi +cd .. && rm -r atmosphere-output -# run the tests +# run test 3 - test for ignoring a bad checksum +mkdir atmosphere-output +cd atmosphere-output +printf "&test_atmosphere_io_nml\n bad_checksum=.true.\n ignore_checksum=.true.\n /" | cat > input.nml run_test ../test_atmosphere_io 6 - cd .. && rm -r atmosphere-output + diff --git a/test_fms/fms2_io/test_bc_restart.F90 b/test_fms/fms2_io/test_bc_restart.F90 index 58fd7d176a..d265e55f0f 100644 --- a/test_fms/fms2_io/test_bc_restart.F90 +++ b/test_fms/fms2_io/test_bc_restart.F90 @@ -21,9 +21,9 @@ !conditions restarts program test_bc_restart -use mpp_mod, only : mpp_init, mpp_exit, mpp_pe, mpp_root_pe, mpp_sync +use mpp_mod, only : mpp_init, mpp_exit, mpp_pe, mpp_root_pe, mpp_sync, input_nml_file use fms2_io_mod, only : FmsNetcdfFile_t, fms2_io_init, open_file, register_restart_field, & - read_restart_bc, write_restart_bc, close_file + register_variable_attribute, read_restart_bc, write_restart_bc, close_file use mpp_domains_mod, only : mpp_get_global_domain, mpp_get_data_domain, mpp_get_compute_domain, & mpp_define_domains, mpp_get_global_domain, domain2d, CORNER @@ -50,9 +50,16 @@ program test_bc_restart integer :: n !< No description type(atm_type) :: atm !< No description +!namelist variables +logical :: ignore_checksum = .false. +logical :: bad_checksum = .false. +namelist /test_bc_restart_nml/ bad_checksum, ignore_checksum + call mpp_init call fms2_io_init +read(input_nml_file, nml=test_bc_restart_nml) + nlon = 144 nlat = 144 @@ -82,6 +89,10 @@ program test_bc_restart if (atm%BCfile_sw_open) then call write_restart_bc(atm%fileobj_sw) + !replace var6 checksum with an incorrect checksum + if (bad_checksum) then + call register_variable_attribute(atm%fileobj_sw, "sst_west", "checksum", "101010101", str_len = 9) + endif call close_file(atm%fileobj_sw) endif @@ -105,7 +116,7 @@ program test_bc_restart call register_bcs(atm, atm%fileobj_ne, atm%fileobj_sw, "sst", layout) if (atm%BCfile_sw_open) then - call read_restart_bc(atm%fileobj_sw) + call read_restart_bc(atm%fileobj_sw, ignore_checksum = ignore_checksum) call close_file(atm%fileobj_sw) endif diff --git a/test_fms/fms2_io/test_bc_restart.sh b/test_fms/fms2_io/test_bc_restart.sh index 7300e3b841..8a6063a13e 100755 --- a/test_fms/fms2_io/test_bc_restart.sh +++ b/test_fms/fms2_io/test_bc_restart.sh @@ -27,7 +27,28 @@ # Set common test settings. . ../test_common.sh -# make an input.nml for mpp_init to read +[ -d bc-restart ] && rm -r bc-restart + +# run test 1 - standard test +mkdir bc-restart +cd bc-restart touch input.nml +run_test ../test_bc_restart 16 +cd .. && rm -r bc-restart + +# run test 2 - test for bad checksum (should fail) +mkdir bc-restart +cd bc-restart +printf "&test_bc_restart_nml\n bad_checksum=.true.\n /" | cat > input.nml +if run_test ../test_bc_restart 16 ; then + echo " test was supposed to fail and didn't " + exit -99 +fi +cd .. && rm -r bc-restart -run_test test_bc_restart 16 +# run test 3 - test for ignoring a bad checksum +mkdir bc-restart +cd bc-restart +printf "&test_bc_restart_nml\n bad_checksum=.true.\n ignore_checksum=.true./" | cat > input.nml +run_test ../test_bc_restart 16 +cd .. && rm -r bc-restart