Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1594: Fix for new_file_freq, start_time, and file_duration keys in diag manager #1633

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion diag_manager/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ diag_util_mod.$(FC_MODEXT): diag_data_mod.$(FC_MODEXT) diag_axis_mod.$(FC_MODEXT
diag_grid_mod.$(FC_MODEXT) fms_diag_time_utils_mod.$(FC_MODEXT) fms_diag_bbox_mod.$(FC_MODEXT)
fms_diag_time_utils_mod.$(FC_MODEXT): diag_data_mod.$(FC_MODEXT)
diag_table_mod.$(FC_MODEXT): diag_data_mod.$(FC_MODEXT) diag_util_mod.$(FC_MODEXT)
fms_diag_yaml_mod.$(FC_MODEXT): diag_data_mod.$(FC_MODEXT)
fms_diag_yaml_mod.$(FC_MODEXT): diag_data_mod.$(FC_MODEXT) fms_diag_time_utils_mod.$(FC_MODEXT)
fms_diag_object_mod.$(FC_MODEXT): diag_data_mod.$(FC_MODEXT) fms_diag_file_object_mod.$(FC_MODEXT) fms_diag_field_object_mod.$(FC_MODEXT) fms_diag_yaml_mod.$(FC_MODEXT) \
fms_diag_time_utils_mod.$(FC_MODEXT) \
fms_diag_output_buffer_mod.$(FC_MODEXT) \
Expand Down
3 changes: 3 additions & 0 deletions diag_manager/diag_manager.F90
Original file line number Diff line number Diff line change
Expand Up @@ -3859,6 +3859,9 @@ SUBROUTINE diag_manager_set_time_end(Time_end_in)
TYPE (time_type), INTENT(in) :: Time_end_in

Time_end = Time_end_in
if (use_modern_diag) then
call fms_diag_object%set_time_end(time_end_in)
endif

END SUBROUTINE diag_manager_set_time_end

Expand Down
66 changes: 44 additions & 22 deletions diag_manager/fms_diag_file_object.F90
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ module fms_diag_file_object_mod
procedure :: write_field_metadata
procedure :: write_axis_data
procedure :: writing_on_this_pe
procedure :: is_time_to_write
procedure :: check_file_times
procedure :: is_time_to_close_file
procedure :: write_time_data
procedure :: update_next_write
Expand All @@ -200,6 +200,7 @@ module fms_diag_file_object_mod
procedure :: close_diag_file
procedure :: set_model_time
procedure :: get_model_time
procedure :: time_to_start_doing_math
end type fmsDiagFileContainer_type

!type(fmsDiagFile_type), dimension (:), allocatable, target :: FMS_diag_file !< The array of diag files
Expand Down Expand Up @@ -264,8 +265,12 @@ logical function fms_diag_files_object_init (files_array)
!! Set this to the time passed in to diag_manager_init
!! This will be the base_time if nothing was passed in
!! This time is appended to the filename if the prepend_date namelist is .True.
obj%start_time = diag_init_time
obj%last_output = diag_init_time
if (obj%has_file_start_time()) then
obj%start_time = obj%get_file_start_time()
else
obj%start_time = diag_init_time
endif
obj%last_output = obj%start_time
obj%model_time = diag_init_time
obj%next_output = diag_time_inc(obj%start_time, obj%get_file_freq(), obj%get_file_frequnit())
obj%next_next_output = diag_time_inc(obj%next_output, obj%get_file_freq(), obj%get_file_frequnit())
Expand All @@ -274,7 +279,12 @@ logical function fms_diag_files_object_init (files_array)
obj%next_close = diag_time_inc(obj%start_time, obj%get_file_new_file_freq(), &
obj%get_file_new_file_freq_units())
else
obj%next_close = diag_time_inc(obj%start_time, VERY_LARGE_FILE_FREQ, DIAG_DAYS)
if (obj%has_file_duration()) then
obj%next_close = diag_time_inc(obj%start_time, obj%get_file_duration(), &
obj%get_file_duration_units())
else
obj%next_close = diag_time_inc(obj%start_time, VERY_LARGE_FILE_FREQ, DIAG_DAYS)
endif
endif
obj%is_file_open = .false.

Expand Down Expand Up @@ -597,7 +607,7 @@ end function get_file_new_file_freq_units
!! \return Copy of file_start_time
pure function get_file_start_time (this) result(res)
class(fmsDiagFile_type), intent(in) :: this !< The file object
character (len=:), allocatable :: res
type(time_type):: res
res = this%diag_yaml_file%get_file_start_time()
end function get_file_start_time

Expand Down Expand Up @@ -639,6 +649,7 @@ pure function is_done_writing_data (this) result(res)
class(fmsDiagFile_type), intent(in) :: this !< The file object
logical :: res
res = this%done_writing_data
if (this%is_file_open) res = .false.
end function is_done_writing_data

!> \brief Checks if file_fname is allocated in the yaml object
Expand Down Expand Up @@ -1014,6 +1025,11 @@ subroutine add_start_time(this, start_time)
!! this%start_time was already set to the diag_init_time
if (start_time .eq. diag_init_time) return

!< If the start_time sent is is greater than or equal to the start time already
!! in the diag file obj return because either this%start_time was already updated
!! or the file has start_time defined in the yaml
if (this%start_time >= start_time) return

if (this%start_time .ne. diag_init_time) then
!> If the this%start_time is not equal to the diag_init_time from the diag_table
!! this%start_time was already updated so make sure it is the same for the current variable
Expand Down Expand Up @@ -1383,11 +1399,14 @@ end subroutine write_field_data

!> \brief Determine if it is time to close the file
!! \return .True. if it is time to close the file
logical function is_time_to_close_file (this, time_step)
logical function is_time_to_close_file (this, time_step, force_close)
class(fmsDiagFileContainer_type), intent(in), target :: this !< The file object
TYPE(time_type), intent(in) :: time_step !< Current model step time
logical, intent(in) :: force_close !< if .true. return true

if (time_step >= this%FMS_diag_file%next_close) then
if (force_close) then
is_time_to_close_file = .true.
elseif (time_step >= this%FMS_diag_file%next_close) then
is_time_to_close_file = .true.
else
if (this%FMS_diag_file%is_static) then
Expand All @@ -1398,8 +1417,18 @@ logical function is_time_to_close_file (this, time_step)
endif
end function

!> \brief Determine if it is time to start doing mathz
!! \return .True. if it is time to start doing mathz
logical function time_to_start_doing_math (this)
class(fmsDiagFileContainer_type), intent(in), target :: this !< The file object
time_to_start_doing_math = .false.
if (this%FMS_diag_file%model_time >= this%FMS_diag_file%start_time) then
time_to_start_doing_math = .true.
endif
end function

!> \brief Determine if it is time to "write" to the file
logical function is_time_to_write(this, time_step, output_buffers, diag_fields, do_not_write)
subroutine check_file_times(this, time_step, output_buffers, diag_fields, do_not_write)
class(fmsDiagFileContainer_type), intent(inout), target :: this !< The file object
TYPE(time_type), intent(in) :: time_step !< Current model step time
type(fmsDiagOutputBuffer_type), intent(in) :: output_buffers(:) !< Array of output buffer.
Expand All @@ -1411,7 +1440,6 @@ logical function is_time_to_write(this, time_step, output_buffers, diag_fields,

do_not_write = .false.
if (time_step > this%FMS_diag_file%next_output) then
is_time_to_write = .true.
if (this%FMS_diag_file%is_static) return
if (time_step > this%FMS_diag_file%next_next_output) then
if (this%FMS_diag_file%get_file_freq() .eq. 0) then
Expand All @@ -1421,9 +1449,7 @@ logical function is_time_to_write(this, time_step, output_buffers, diag_fields,
call this%FMS_diag_file%check_buffer_times(output_buffers, diag_fields)
this%FMS_diag_file%next_output = time_step
this%FMS_diag_file%next_next_output = time_step
is_time_to_write = .true.
endif
return
elseif (this%FMS_diag_file%num_registered_fields .eq. 0) then
!! If no variables have been registered, write a dummy time dimension for the first level
!! At least one time level is needed for the combiner to work ...
Expand All @@ -1433,26 +1459,20 @@ logical function is_time_to_write(this, time_step, output_buffers, diag_fields,
this%FMS_diag_file%data_has_been_written = .true.
this%FMS_diag_file%unlim_dimension_level = 1
endif
is_time_to_write =.false.
else
!! Only fail if send data has actually been called for at least one variable
if (this%FMS_diag_file%has_send_data_been_called(output_buffers, .false.)) &
call mpp_error(FATAL, this%FMS_diag_file%get_file_fname()//&
": diag_manager_mod: You skipped a time_step. Be sure that diag_send_complete is called at every "//&
"time_step needed by the file.")
is_time_to_write =.false.
endif
endif
else
is_time_to_write = .false.
if (this%FMS_diag_file%is_static) then
! This is to ensure that static files get finished in the begining of the run
if (this%FMS_diag_file%unlim_dimension_level .eq. 1) is_time_to_write = .true.
else if(this%FMS_diag_file%get_file_freq() .eq. 0) then
if(this%FMS_diag_file%get_file_freq() .eq. 0) then
do_not_write = .true.
endif
endif
end function is_time_to_write
end subroutine check_file_times

!> \brief Determine if the current PE has data to write
logical function writing_on_this_pe(this)
Expand Down Expand Up @@ -1532,7 +1552,6 @@ subroutine update_current_new_file_freq_index(this, time_step)
diag_file%next_output = diag_file%no_more_data
diag_file%next_next_output = diag_file%no_more_data
diag_file%last_output = diag_file%no_more_data
diag_file%next_close = diag_file%no_more_data
endif
endif

Expand Down Expand Up @@ -1776,10 +1795,11 @@ subroutine write_axis_data(this, diag_axis)
end subroutine write_axis_data

!< @brief Closes the diag_file
subroutine close_diag_file(this, output_buffers, diag_fields)
subroutine close_diag_file(this, output_buffers, model_end_time, diag_fields)
class(fmsDiagFileContainer_type), intent(inout), target :: this !< The file object
type(fmsDiagOutputBuffer_type), intent(in) :: output_buffers(:) !< Array of output buffers
!! This is needed for error checking
type(time_type), intent(in) :: model_end_time !< Time that simulation ends
type(fmsDiagField_type), intent(in), optional :: diag_fields(:) !< Array of diag fields
!! This is needed for error checking

Expand All @@ -1805,9 +1825,11 @@ subroutine close_diag_file(this, output_buffers, diag_fields)
this%FMS_diag_file%get_file_new_file_freq(), &
this%FMS_diag_file%get_file_new_file_freq_units())
else
this%FMS_diag_file%next_close = diag_time_inc(this%FMS_diag_file%next_close, VERY_LARGE_FILE_FREQ, DIAG_DAYS)
this%FMS_diag_file%next_close = model_end_time
endif

if (this%FMS_diag_file%model_time >= model_end_time) &
this%FMS_diag_file%done_writing_data = .true.
if (this%FMS_diag_file%has_send_data_been_called(output_buffers, .True., diag_fields)) return
end subroutine close_diag_file

Expand Down
28 changes: 20 additions & 8 deletions diag_manager/fms_diag_object.F90
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ module fms_diag_object_mod
logical, private :: fields_initialized=.false. !< True if the fmsDiagObject is initialized
logical, private :: buffers_initialized=.false. !< True if the fmsDiagObject is initialized
logical, private :: axes_initialized=.false. !< True if the fmsDiagObject is initialized
type(time_type) :: model_end_time !< The time that the simulation is going to end
!! (set by calling diag_manager_set_time_end)
#endif
contains
procedure :: init => fms_diag_object_init
Expand All @@ -94,6 +96,7 @@ module fms_diag_object_mod
procedure :: fms_diag_field_add_cell_measures
procedure :: allocate_diag_field_output_buffers
procedure :: fms_diag_compare_window
procedure :: set_time_end
#ifdef use_yaml
procedure :: get_diag_buffer
#endif
Expand Down Expand Up @@ -821,14 +824,14 @@ subroutine fms_diag_do_io(this, end_time)

!< Go away if the file is a subregional file and the current PE does not have any data for it
if (.not. diag_file%writing_on_this_pe()) cycle
if (diag_file%FMS_diag_file%is_done_writing_data()) cycle

if (present (end_time)) then
force_write = .true.
model_time => end_time
else
model_time => diag_file%get_model_time()
endif
if (diag_file%FMS_diag_file%is_done_writing_data()) cycle

call diag_file%open_diag_file(model_time, file_is_opened_this_time_step)
if (file_is_opened_this_time_step) then
Expand All @@ -842,7 +845,7 @@ subroutine fms_diag_do_io(this, end_time)
call diag_file%write_axis_data(this%diag_axis)
endif

finish_writing = diag_file%is_time_to_write(model_time, this%FMS_diag_output_buffers, &
call diag_file%check_file_times(model_time, this%FMS_diag_output_buffers, &
this%FMS_diag_fields, do_not_write)
unlim_dim_was_increased = .false.

Expand Down Expand Up @@ -881,16 +884,15 @@ subroutine fms_diag_do_io(this, end_time)
call diag_file%write_time_data()
call diag_file%flush_diag_file()
call diag_file%update_next_write(model_time)
endif

if (finish_writing) then
call diag_file%update_current_new_file_freq_index(model_time)
if (diag_file%is_time_to_close_file(model_time)) call diag_file%close_diag_file(this%FMS_diag_output_buffers, &
diag_fields = this%FMS_diag_fields)
if (diag_file%is_time_to_close_file(model_time, force_write)) &
call diag_file%close_diag_file(this%FMS_diag_output_buffers, &
this%model_end_time, diag_fields = this%FMS_diag_fields)
else if (force_write) then
call diag_file%prepare_for_force_write()
call diag_file%write_time_data()
call diag_file%close_diag_file(this%FMS_diag_output_buffers, diag_fields = this%FMS_diag_fields)
call diag_file%close_diag_file(this%FMS_diag_output_buffers, &
this%model_end_time, diag_fields = this%FMS_diag_fields)
endif
enddo
#endif
Expand Down Expand Up @@ -979,6 +981,7 @@ function fms_diag_do_reduction(this, field_data, diag_field_id, oor_mask, weight
if (buffer_ptr%is_done_with_math()) cycle

if (present(time)) call file_ptr%set_model_time(time)
if (.not. file_ptr%time_to_start_doing_math()) cycle

bounds_out = bounds
if (.not. using_blocking) then
Expand Down Expand Up @@ -1503,4 +1506,13 @@ function fms_diag_compare_window(this, field, field_id, &
#endif
end function fms_diag_compare_window

!> @brief Set the model_end_time in a diag object
subroutine set_time_end(this, time_end_in)
class(fmsDiagObject_type), intent(inout) :: this !< Diag Object
type(time_type), intent(in) :: time_end_in !< Time at the end of the simulation
#ifdef use_yaml
this%model_end_time = time_end_in
#endif
end subroutine

end module fms_diag_object_mod
37 changes: 36 additions & 1 deletion diag_manager/fms_diag_time_utils.F90
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
module fms_diag_time_utils_mod

use time_manager_mod, only: time_type, increment_date, increment_time, get_calendar_type, NO_CALENDAR, leap_year, &
get_date, get_time, operator(>), operator(<), operator(-), set_date
get_date, get_time, operator(>), operator(<), operator(-), set_date, set_time
use diag_data_mod, only: END_OF_RUN, EVERY_TIME, DIAG_SECONDS, DIAG_MINUTES, DIAG_HOURS, DIAG_DAYS, DIAG_MONTHS, &
DIAG_YEARS, use_clock_average
USE constants_mod, ONLY: SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MINUTE
Expand All @@ -40,6 +40,7 @@ module fms_diag_time_utils_mod
public :: diag_time_inc
public :: get_time_string
public :: get_date_dif
public :: set_time_type

contains

Expand Down Expand Up @@ -383,4 +384,38 @@ REAL FUNCTION get_date_dif(t2, t1, units)
CALL mpp_error(FATAL, 'diag_util_mod::diag_date_dif illegal time units')
END IF
END FUNCTION get_date_dif

!> @brief Sets up a time_type based on 6 member array of integers defining the
!! [year month day hour min sec]
subroutine set_time_type(time_int, time)
integer, intent(in) :: time_int(6) !< The time in the format [year month day hour min second]
type(time_type), intent(inout) :: time !< The time converted to the time_type

integer :: year !< Year of the time type
integer :: month !< Month of the time type
integer :: day !< Day of the time type
integer :: hour !< Hour of the time type
integer :: minute !< Minute of the time type
integer :: second !< Second of the time type

year = time_int(1)
month = time_int(2)
day = time_int(3)
hour = time_int(4)
minute = time_int(5)
second = time_int(6)

! Set up the time type for time passed in
IF ( get_calendar_type() /= NO_CALENDAR ) THEN
IF ( year==0 .OR. month==0 .OR. day==0 ) THEN
call mpp_error(FATAL, 'fms_diag_time_utils_mod::set_time_type'//&
& 'The year/month/day can not equal zero')
END IF
time = set_date(year, month, day, hour, minute, second)
ELSE
! No calendar - ignore year and month
time = set_time(NINT(hour*SECONDS_PER_HOUR)+NINT(minute*SECONDS_PER_MINUTE)+second, &
& day)
END IF
end subroutine set_time_type
end module fms_diag_time_utils_mod
Loading
Loading