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

add time sum reduction to dmUpdate #1375

Merged
merged 13 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from 7 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: 5 additions & 0 deletions diag_manager/fms_diag_object.F90
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,11 @@ function fms_diag_do_reduction(this, field_data, diag_field_id, oor_mask, weight
return
endif
case (time_sum)
error_msg = buffer_ptr%do_time_sum_wrapper(field_data, oor_mask, field_ptr%get_mask_variant(), &
bounds_in, bounds_out, missing_value)
if (trim(error_msg) .ne. "") then
return
endif
case (time_average)
case (time_power)
case (time_rms)
Expand Down
37 changes: 36 additions & 1 deletion diag_manager/fms_diag_output_buffer.F90
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ module fms_diag_output_buffer_mod
use fms2_io_mod, only: FmsNetcdfFile_t, write_data, FmsNetcdfDomainFile_t, FmsNetcdfUnstructuredDomainFile_t
use fms_diag_yaml_mod, only: diag_yaml
use fms_diag_bbox_mod, only: fmsDiagIbounds_type
use fms_diag_reduction_methods_mod, only: do_time_none, do_time_min, do_time_max
use fms_diag_reduction_methods_mod, only: do_time_none, do_time_min, do_time_max, do_time_sum
use fms_diag_time_utils_mod, only: diag_time_inc

implicit none
Expand Down Expand Up @@ -78,6 +78,7 @@ module fms_diag_output_buffer_mod
procedure :: do_time_none_wrapper
procedure :: do_time_min_wrapper
procedure :: do_time_max_wrapper
procedure :: do_time_sum_wrapper

end type fmsDiagOutputBuffer_type

Expand Down Expand Up @@ -571,5 +572,39 @@ function do_time_max_wrapper(this, field_data, mask, is_masked, bounds_in, bound
end select
end select
end function do_time_max_wrapper

!> @brief Does the time_sum reduction method on the buffer object
!! @return Error message if the math was not successful
function do_time_sum_wrapper(this, field_data, mask, is_masked, bounds_in, bounds_out, missing_value) &
result(err_msg)
class(fmsDiagOutputBuffer_type), intent(inout) :: this !< buffer object to write
class(*), intent(in) :: field_data(:,:,:,:) !< Buffer data for current time
type(fmsDiagIbounds_type), intent(in) :: bounds_in !< Indicies for the buffer passed in
type(fmsDiagIbounds_type), intent(in) :: bounds_out !< Indicies for the output buffer
logical, intent(in) :: mask(:,:,:,:) !< Mask for the field
logical, intent(in) :: is_masked !< .True. if the field has a mask
real(kind=r8_kind), intent(in) :: missing_value !< Missing_value for data points that are masked
character(len=50) :: err_msg

!TODO This will be expanded for integers
err_msg = ""
select type (output_buffer => this%buffer)
type is (real(kind=r8_kind))
select type (field_data)
type is (real(kind=r8_kind))
call do_time_sum(output_buffer, field_data, mask, is_masked, bounds_in, bounds_out, missing_value)
class default
err_msg="do_time_sum_wrapper::the output buffer and the buffer send in are not of the same type (r8_kind)"
end select
type is (real(kind=r4_kind))
select type (field_data)
type is (real(kind=r4_kind))
call do_time_sum(output_buffer, field_data, mask, is_masked, bounds_in, bounds_out, &
real(missing_value, kind=r4_kind))
class default
err_msg="do_time_sum_wrapper::the output buffer and the buffer send in are not of the same type (r4_kind)"
thomas-robinson marked this conversation as resolved.
Show resolved Hide resolved
end select
end select
end function do_time_sum_wrapper
#endif
end module fms_diag_output_buffer_mod
8 changes: 7 additions & 1 deletion diag_manager/fms_diag_reduction_methods.F90
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module fms_diag_reduction_methods_mod
private

public :: check_indices_order, init_mask, set_weight
public :: do_time_none, do_time_min, do_time_max
public :: do_time_none, do_time_min, do_time_max, do_time_sum

!> @brief Does the time_none reduction method. See include/fms_diag_reduction_methods.inc
!TODO This needs to be extended to integers
Expand All @@ -55,6 +55,12 @@ module fms_diag_reduction_methods_mod
module procedure do_time_max_r4, do_time_max_r8
end interface do_time_max

!> @brief Does the time_sum reduction method. See include/fms_diag_reduction_methods.inc
!TODO This needs to be extended to integers
interface do_time_sum
module procedure do_time_sum_r4, do_time_sum_r8
end interface

contains

!> @brief Checks improper combinations of is, ie, js, and je.
Expand Down
69 changes: 68 additions & 1 deletion diag_manager/include/fms_diag_reduction_methods.inc
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,71 @@ subroutine DO_TIME_MAX_ (data_out, data_in, mask, is_masked, bounds_in, bounds_o
enddo
enddo
endif
end subroutine DO_TIME_MAX_
end subroutine DO_TIME_MAX_

!> Update the output buffer and counter for the time_sum reduction
!! Updates elements of the running field output buffer (data_out)
!! For time_sum, just sums passed field data into the output buffer
subroutine DO_TIME_SUM_(data_out, data_in, mask, is_masked, bounds_in, bounds_out, missing_value )
real(FMS_TRM_KIND_), intent(inout) :: data_out(:,:,:,:,:) !< output data
real(FMS_TRM_KIND_), intent(in) :: data_in(:,:,:,:) !< data to update the buffer with
logical, intent(in) :: mask(:,:,:,:) !< mask
logical, intent(in) :: is_masked !< .True. if the field is using a mask
type(fmsDiagIbounds_type), intent(in) :: bounds_in !< indices indicating the correct portion
!! of the input buffer
type(fmsDiagIbounds_type), intent(in) :: bounds_out !< indices indicating the correct portion
!! of the output buffer
real(FMS_TRM_KIND_), intent(in) :: missing_value !< Missing_value for data points that are masked
thomas-robinson marked this conversation as resolved.
Show resolved Hide resolved

integer :: is_in, ie_in, js_in, je_in, ks_in, ke_in !< Starting and ending indices of each dimention for
!! the input buffer
integer :: is_out, ie_out, js_out, je_out, ks_out, ke_out !< Starting and ending indices of each dimention for
!! the output buffer
integer :: i, j, k, l !< For looping


is_out = bounds_out%get_imin()
ie_out = bounds_out%get_imax()
js_out = bounds_out%get_jmin()
je_out = bounds_out%get_jmax()
ks_out = bounds_out%get_kmin()
ke_out = bounds_out%get_kmax()

is_in = bounds_in%get_imin()
ie_in = bounds_in%get_imax()
js_in = bounds_in%get_jmin()
je_in = bounds_in%get_jmax()
ks_in = bounds_in%get_kmin()
ke_in = bounds_in%get_kmax()

!> Seperated this loops for performance. If is_masked = .false. (i.e "mask" and "rmask" were never passed in)
!! then mask will always be .True. so the if (mask) is redudant.
if (is_masked) then
do l = 0, size(data_out, 4) - 1
do k = 0, ke_out - ks_out
do j = 0, je_out - js_out
do i = 0, ie_out - is_out
if (mask(is_in + i, js_in + j, ks_in + k, l + 1)) then
data_out(is_out + i, js_out + j, ks_out + k, l + 1, 1) = &
data_out(is_out + i, js_out + j, ks_out + k, l + 1, 1) &
+ data_in(is_in +i, js_in + j, ks_in + k, l + 1)
else
data_out(is_out + i, js_out + j, ks_out + k, l + 1, 1) = missing_value
endif
enddo
enddo
enddo
enddo
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be reduced to a where and elsewhere constuct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that works, added in 618bb06

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope this works

else
! doesn't need to loop through l if no mask, just sums the 1d slices
do k = 0, ke_out - ks_out
do j = 0, je_out - js_out
do i = 0, ie_out - is_out
data_out(is_out + i, js_out + j, ks_out + k, :, 1) = &
data_out(is_out + i, js_out + j, ks_out + k, :, 1) &
+ data_in(is_in +i, js_in + j, ks_in + k, :)
enddo
enddo
enddo
endif
end subroutine DO_TIME_SUM_
3 changes: 3 additions & 0 deletions diag_manager/include/fms_diag_reduction_methods_r4.fh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
#undef DO_TIME_MAX_
#define DO_TIME_MAX_ do_time_max_r4

#undef DO_TIME_SUM_
#define DO_TIME_SUM_ do_time_sum_r4

#include "fms_diag_reduction_methods.inc"

!> @}
Expand Down
3 changes: 3 additions & 0 deletions diag_manager/include/fms_diag_reduction_methods_r8.fh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
#undef DO_TIME_MAX_
#define DO_TIME_MAX_ do_time_max_r8

#undef DO_TIME_SUM_
#define DO_TIME_SUM_ do_time_sum_r8

#include "fms_diag_reduction_methods.inc"

!> @}
Expand Down
8 changes: 5 additions & 3 deletions test_fms/diag_manager/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ LDADD = $(top_builddir)/libFMS/libFMS.la
check_PROGRAMS = test_diag_manager test_diag_manager_time \
test_diag_dlinked_list test_diag_yaml test_diag_ocean test_modern_diag test_diag_buffer \
test_flexible_time test_diag_update_buffer test_reduction_methods check_time_none \
check_time_min check_time_max
check_time_min check_time_max check_time_sum

# This is the source code for the test.
test_diag_manager_SOURCES = test_diag_manager.F90
Expand All @@ -47,18 +47,20 @@ test_reduction_methods_SOURCES = testing_utils.F90 test_reduction_methods.F90
check_time_none_SOURCES = testing_utils.F90 check_time_none.F90
check_time_min_SOURCES = testing_utils.F90 check_time_min.F90
check_time_max_SOURCES = testing_utils.F90 check_time_max.F90
check_time_sum_SOURCES = testing_utils.F90 check_time_sum.F90

TEST_EXTENSIONS = .sh
SH_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
$(abs_top_srcdir)/test_fms/tap-driver.sh

# Run the test.
TESTS = test_diag_manager2.sh test_time_none.sh test_time_min.sh test_time_max.sh
TESTS = test_diag_manager2.sh test_time_none.sh test_time_min.sh test_time_max.sh test_time_sum.sh

testing_utils.mod: testing_utils.$(OBJEXT)

# Copy over other needed files to the srcdir
EXTRA_DIST = test_diag_manager2.sh check_crashes.sh test_time_none.sh test_time_min.sh test_time_max.sh
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

if USING_YAML
skipflag=""
Expand Down
Loading