diff --git a/diag_manager/fms_diag_file_object.F90 b/diag_manager/fms_diag_file_object.F90 index 1d0d40e7a..7e0c44647 100644 --- a/diag_manager/fms_diag_file_object.F90 +++ b/diag_manager/fms_diag_file_object.F90 @@ -28,13 +28,14 @@ module fms_diag_file_object_mod use fms2_io_mod, only: FmsNetcdfFile_t, FmsNetcdfUnstructuredDomainFile_t, FmsNetcdfDomainFile_t, & get_instance_filename, open_file, close_file, get_mosaic_tile_file, unlimited, & register_axis, register_field, register_variable_attribute, write_data, & - dimension_exists, register_global_attribute + dimension_exists, register_global_attribute, flush_file use diag_data_mod, only: DIAG_NULL, NO_DOMAIN, max_axes, SUB_REGIONAL, get_base_time, DIAG_NOT_REGISTERED, & TWO_D_DOMAIN, UG_DOMAIN, prepend_date, DIAG_DAYS, VERY_LARGE_FILE_FREQ, & get_base_year, get_base_month, get_base_day, get_base_hour, get_base_minute, & get_base_second, time_unit_list, time_average, time_rms, time_max, time_min, time_sum, & time_diurnal, time_power, time_none, avg_name, no_units, pack_size_str, & - middle_time, begin_time, end_time, MAX_STR_LEN, index_gridtype, latlon_gridtype, null_gridtype + middle_time, begin_time, end_time, MAX_STR_LEN, index_gridtype, latlon_gridtype, & + null_gridtype, flush_nc_files use time_manager_mod, only: time_type, operator(>), operator(/=), operator(==), get_date, get_calendar_type, & VALID_CALENDAR_TYPES, operator(>=), date_to_string, & OPERATOR(/), OPERATOR(+), operator(<) @@ -192,6 +193,7 @@ module fms_diag_file_object_mod procedure :: init_unlim_dim procedure :: update_current_new_file_freq_index procedure :: get_unlim_dimension_level + procedure :: flush_diag_file procedure :: get_next_output procedure :: get_next_next_output procedure :: close_diag_file @@ -1473,10 +1475,8 @@ subroutine write_time_data(this) diag_file => this%FMS_diag_file fms2io_fileobj => diag_file%fms2io_fileobj - !< If data has not been written for the current unlimited dimension - !! ignore this. The diag_file%unlim_dimension_level .ne. 1 is there to ensure - !! that at least one time level is written (this is needed for the combiner) - if (.not. diag_file%data_has_been_written .and. diag_file%unlim_dimension_level .ne. 1) return + !< If data has not been written for the current unlimited dimension leave the subroutine + if (.not. diag_file%data_has_been_written) return if (diag_file%get_time_ops()) then middle_time = (diag_file%last_output+diag_file%next_output)/2 @@ -1591,6 +1591,15 @@ pure function get_unlim_dimension_level(this) & res = this%FMS_diag_file%unlim_dimension_level end function +!> \brief Flushes the netcdf file to disk if flush_nc_files is set to .True. in the namelist +subroutine flush_diag_file(this) + class(fmsDiagFileContainer_type), intent(inout), target :: this !< The file object + + if (flush_nc_files) then + call flush_file(this%FMS_diag_file%fms2io_fileobj) + endif +end subroutine flush_diag_file + !> \brief Get the next_output for the file object !! \return The next_output pure function get_next_output(this) & diff --git a/diag_manager/fms_diag_object.F90 b/diag_manager/fms_diag_object.F90 index 465459061..794a1c6a4 100644 --- a/diag_manager/fms_diag_object.F90 +++ b/diag_manager/fms_diag_object.F90 @@ -873,6 +873,7 @@ subroutine fms_diag_do_io(this, end_time) if (unlim_dim_was_increased) then call diag_file%write_time_data() + call diag_file%flush_diag_file() call diag_file%update_next_write(model_time) endif diff --git a/test_fms/diag_manager/Makefile.am b/test_fms/diag_manager/Makefile.am index e3c7a1e8a..df5a8a19f 100644 --- a/test_fms/diag_manager/Makefile.am +++ b/test_fms/diag_manager/Makefile.am @@ -29,7 +29,7 @@ LDADD = $(top_builddir)/libFMS/libFMS.la # Build this test program. check_PROGRAMS = test_diag_manager test_diag_manager_time \ - test_diag_yaml test_diag_ocean test_modern_diag test_diag_buffer \ + test_diag_yaml test_diag_ocean test_modern_diag test_diag_buffer test_flush_nc_file\ test_flexible_time test_diag_update_buffer test_reduction_methods check_time_none \ check_time_min check_time_max check_time_sum check_time_avg test_diag_diurnal check_time_diurnal \ check_time_pow check_time_rms check_subregional test_cell_measures test_var_masks \ @@ -47,6 +47,7 @@ test_diag_ocean_SOURCES = test_diag_ocean.F90 test_modern_diag_SOURCES = test_modern_diag.F90 test_diag_buffer_SOURCES= test_diag_buffer.F90 test_flexible_time_SOURCES = test_flexible_time.F90 +test_flush_nc_file_SOURCES = test_flush_nc_file.F90 test_diag_out_yaml_SOURCES = test_diag_out_yaml.F90 test_reduction_methods_SOURCES = testing_utils.F90 test_reduction_methods.F90 test_diag_diurnal_SOURCES = testing_utils.F90 test_diag_diurnal.F90 @@ -72,7 +73,7 @@ SH_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ TESTS = test_diag_manager2.sh test_time_none.sh test_time_min.sh test_time_max.sh test_time_sum.sh \ test_time_avg.sh test_time_pow.sh test_time_rms.sh test_time_diurnal.sh test_cell_measures.sh \ test_subregional.sh test_var_masks.sh test_multiple_send_data.sh test_output_every_freq.sh \ - test_dm_weights.sh + test_dm_weights.sh test_flush_nc_file.sh testing_utils.mod: testing_utils.$(OBJEXT) @@ -80,7 +81,7 @@ testing_utils.mod: testing_utils.$(OBJEXT) EXTRA_DIST = test_diag_manager2.sh check_crashes.sh test_time_none.sh test_time_min.sh test_time_max.sh \ test_time_sum.sh test_time_avg.sh test_time_pow.sh test_time_rms.sh test_time_diurnal.sh \ test_cell_measures.sh test_subregional.sh test_var_masks.sh test_multiple_send_data.sh \ - test_dm_weights.sh test_output_every_freq.sh + test_flush_nc_file.sh test_dm_weights.sh test_output_every_freq.sh if USING_YAML skipflag="" diff --git a/test_fms/diag_manager/check_var_masks.F90 b/test_fms/diag_manager/check_var_masks.F90 index d1d3b1772..b9cfe99a0 100644 --- a/test_fms/diag_manager/check_var_masks.F90 +++ b/test_fms/diag_manager/check_var_masks.F90 @@ -34,6 +34,7 @@ program check_var_masks real :: ans_var_mask real :: ans_var integer :: i, j + real :: time_data(2) call fms_init() @@ -49,6 +50,14 @@ program check_var_masks call get_dimension_size(fileobj, "y", ny) if (ny .ne. 180) call mpp_error(FATAL, "y is not the correct size!") + call read_data(fileobj, "time", time_data(1)) + if (time_data(1) .ne. real(12.))& + call mpp_error(FATAL, "The time data is not the expected result") + + call read_data(fileobj, "time_bnds", time_data) + if (time_data(1) .ne. real(0.) .or. time_data(2) .ne. real(24.)) & + call mpp_error(FATAL, "The time bnds data is not the expected result") + allocate(vardata(nx,ny)) ans_var_mask = 0. diff --git a/test_fms/diag_manager/test_flush_nc_file.F90 b/test_fms/diag_manager/test_flush_nc_file.F90 new file mode 100644 index 000000000..b0134f4a0 --- /dev/null +++ b/test_fms/diag_manager/test_flush_nc_file.F90 @@ -0,0 +1,108 @@ +!*********************************************************************** +!* GNU Lesser General Public License +!* +!* This file is part of the GFDL Flexible Modeling System (FMS). +!* +!* FMS is free software: you can redistribute it and/or modify it under +!* the terms of the GNU Lesser General Public License as published by +!* the Free Software Foundation, either version 3 of the License, or (at +!* your option) any later version. +!* +!* FMS is distributed in the hope that it will be useful, but WITHOUT +!* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +!* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +!* for more details. +!* +!* You should have received a copy of the GNU Lesser General Public +!* License along with FMS. If not, see . +!*********************************************************************** + +!> @brief This programs tests when flush_nc_file=.true. +program test_flush_nc_file + use fms_mod, only: fms_init, fms_end + use diag_manager_mod + use mpp_mod + use mpp_domains_mod + use platform_mod, only: r8_kind, r4_kind + use time_manager_mod, only: time_type, set_calendar_type, set_date, JULIAN, set_time, OPERATOR(+) + use fms2_io_mod + use fms_diag_yaml_mod + + implicit none + + type(time_type) :: Time !< Time of the simulation + type(time_type) :: Time_step !< Time_step of the simulation + integer :: nx !< Number of x points + integer :: ny !< Number of y points + integer :: nz !< Number of z points + integer :: id_x !< Axis id for the x dimension + integer :: id_y !< Axis id for the y dimension + integer :: id_var1 !< Field id for 1st variable + logical :: used !< Dummy argument to send_data + real, allocatable :: x(:) !< X axis data + real, allocatable :: y(:) !< Y axis_data + real, allocatable :: var1_data(:,:) !< Data for variable 1 + integer :: i !< For do loops + + call fms_init + call set_calendar_type(JULIAN) + call diag_manager_init + + nx = 360 + ny = 180 + + allocate(x(nx), y(ny)) + allocate(var1_data(nx,ny)) + do i=1,nx + x(i) = i + enddo + do i=1,ny + y(i) = -91 + i + enddo + + Time = set_date(2,1,1,0,0,0) + Time_step = set_time (3600,0) !< 1 hour + + id_x = diag_axis_init('x', x, 'point_E', 'x', long_name='point_E') + id_y = diag_axis_init('y', y, 'point_N', 'y', long_name='point_N') + id_var1 = register_diag_field ('atmos', 'ua', (/id_x, id_y/), Time) + + call diag_manager_set_time_end(set_date(2,1,2,0,0,0)) + do i = 1, 24 + Time = Time + Time_step + var1_data = real(i) + used = send_data(id_var1, var1_data, Time) + if (mpp_pe() .eq. mpp_root_pe()) print *, "Calling send_data::", i + call diag_send_complete(Time_step) + call mpp_sync() + ! The file should have been flushed by now + call check_answers(i) + enddo + + call diag_manager_end(Time) + !call check_answers(i) + call fms_end + + contains + subroutine check_answers(time_level) + integer, intent(in) :: time_level + type(FmsNetcdfFile_t) :: fileobj + integer :: ntimes + real, allocatable :: vardata(:,:) + + if (mpp_pe() .ne. mpp_root_pe()) return + if (.not. open_file(fileobj, "test_flush.nc", "read")) & + call mpp_error(FATAL, "unable to open test_flush.nc for reading") + + call get_dimension_size(fileobj, "time", ntimes) + if (ntimes .ne. time_level) call mpp_error(FATAL, "time is not the correct size::", time_level) + + allocate(vardata(nx,ny)) + + call read_data(fileobj, "ua", vardata, unlim_dim_level=i) + if (any(vardata .ne. time_level)) & + call mpp_error(FATAL, "ua is not the expected result") + + call close_file(fileobj) + end subroutine check_answers +end program test_flush_nc_file \ No newline at end of file diff --git a/test_fms/diag_manager/test_flush_nc_file.sh b/test_fms/diag_manager/test_flush_nc_file.sh new file mode 100755 index 000000000..7337bd849 --- /dev/null +++ b/test_fms/diag_manager/test_flush_nc_file.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +#*********************************************************************** +#* GNU Lesser General Public License +#* +#* This file is part of the GFDL Flexible Modeling System (FMS). +#* +#* FMS is free software: you can redistribute it and/or modify it under +#* the terms of the GNU Lesser General Public License as published by +#* the Free Software Foundation, either version 3 of the License, or (at +#* your option) any later version. +#* +#* FMS is distributed in the hope that it will be useful, but WITHOUT +#* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +#* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +#* for more details. +#* +#* You should have received a copy of the GNU Lesser General Public +#* License along with FMS. If not, see . +#*********************************************************************** + +# Set common test settings. +. ../test-lib.sh + +if [ -z "${skipflag}" ]; then +# create and enter directory for in/output files +output_dir + +cat <<_EOF > diag_table.yaml +title: test_nc_flush +base_date: 2 1 1 0 0 0 +diag_files: +- file_name: test_flush + time_units: hours + unlimdim: time + freq: 1 hours + varlist: + - module: atmos + var_name: ua + reduction: average + kind: r4 +_EOF + +# remove any existing files that would result in false passes during checks +rm -f *.nc + +my_test_count=1 +printf "&diag_manager_nml \n use_modern_diag=.true. \n flush_nc_files=.true. \n/" | cat > input.nml +test_expect_success "Running diag_manager with flush_nc_files = .true. (test $my_test_count)" ' + mpirun -n 1 ../test_var_masks +' +fi +test_done