Skip to content

Commit

Permalink
+Add zero_zeros optional arg to MOM_write_field
Browse files Browse the repository at this point in the history
  Added the new zero_zeros optional argument to the 10 MOM_write_field routines
in MOM_io and the 6 rescale_comp_data routines in MOM_domain_infra to cause
negative zeros to replaced with ordinary signless zeros before they are written
out to files.  This has no impact at all on answers, but it does help with
comparisons between rotated restart files, in which meaningless differences
between positive and negative zeros were leading to false differences between
files.  All answers are bitwise identical, and all output is equivalent, but
there are new optional arguments to 16 routines covered by 2 publicly visible
interfaces.
  • Loading branch information
Hallberg-NOAA committed Feb 13, 2025
1 parent 1877681 commit 9aaf5e1
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 48 deletions.
60 changes: 48 additions & 12 deletions config_src/infra/FMS1/MOM_domain_infra.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1259,53 +1259,89 @@ end subroutine redistribute_array_4d


!> Rescale the values of a 4-D array in its computational domain by a constant factor
subroutine rescale_comp_data_4d(domain, array, scale)
subroutine rescale_comp_data_4d(domain, array, scale, zero_zeros)
type(MOM_domain_type), intent(in) :: domain !< MOM domain from which to extract information
real, dimension(:,:,:,:), intent(inout) :: array !< The array which is having the data in its
!! computational domain rescaled
real, intent(in) :: scale !< A scaling factor by which to multiply the
!! values in the computational domain of array
integer :: is, ie, js, je
logical, optional, intent(in) :: zero_zeros !< If present and true, convert negative zeros
!! into ordinary signless zeros.
logical :: unsign_zeros ! If true, convert negative zeros into ordinary signless zeros.
integer :: is, ie, js, je, i, j, k, m

if (scale == 1.0) return
unsign_zeros = .false. ; if (present(zero_zeros)) unsign_zeros = zero_zeros

if ((scale == 1.0) .and. (.not.unsign_zeros)) return

call get_simple_array_i_ind(domain, size(array,1), is, ie)
call get_simple_array_j_ind(domain, size(array,2), js, je)
array(is:ie,js:je,:,:) = scale*array(is:ie,js:je,:,:)
if (scale /= 1.0) &
array(is:ie,js:je,:,:) = scale*array(is:ie,js:je,:,:)

if (unsign_zeros) then ! Convert negative zeros into zeros
do m=1,size(array,4) ; do k=1,size(array,3) ; do j=js,je ; do i=is,ie
if (array(i,j,k,m) == 0.0) array(i,j,k,m) = 0.0
enddo ; enddo ; enddo ; enddo
endif

end subroutine rescale_comp_data_4d

!> Rescale the values of a 3-D array in its computational domain by a constant factor
subroutine rescale_comp_data_3d(domain, array, scale)
subroutine rescale_comp_data_3d(domain, array, scale, zero_zeros)
type(MOM_domain_type), intent(in) :: domain !< MOM domain from which to extract information
real, dimension(:,:,:), intent(inout) :: array !< The array which is having the data in its
!! computational domain rescaled
real, intent(in) :: scale !< A scaling factor by which to multiply the
!! values in the computational domain of array
integer :: is, ie, js, je
logical, optional, intent(in) :: zero_zeros !< If present and true, convert negative zeros
!! into ordinary signless zeros.
logical :: unsign_zeros ! If true, convert negative zeros into ordinary signless zeros.
integer :: is, ie, js, je, i, j, k

if (scale == 1.0) return
unsign_zeros = .false. ; if (present(zero_zeros)) unsign_zeros = zero_zeros

if ((scale == 1.0) .and. (.not.unsign_zeros)) return

call get_simple_array_i_ind(domain, size(array,1), is, ie)
call get_simple_array_j_ind(domain, size(array,2), js, je)
array(is:ie,js:je,:) = scale*array(is:ie,js:je,:)
if (scale /= 1.0) &
array(is:ie,js:je,:) = scale*array(is:ie,js:je,:)

if (unsign_zeros) then ! Convert negative zeros into zeros
do k=1,size(array,3) ; do j=js,je ; do i=is,ie
if (array(i,j,k) == 0.0) array(i,j,k) = 0.0
enddo ; enddo ; enddo
endif

end subroutine rescale_comp_data_3d

!> Rescale the values of a 2-D array in its computational domain by a constant factor
subroutine rescale_comp_data_2d(domain, array, scale)
subroutine rescale_comp_data_2d(domain, array, scale, zero_zeros)
type(MOM_domain_type), intent(in) :: domain !< MOM domain from which to extract information
real, dimension(:,:), intent(inout) :: array !< The array which is having the data in its
!! computational domain rescaled
real, intent(in) :: scale !< A scaling factor by which to multiply the
!! values in the computational domain of array
integer :: is, ie, js, je
logical, optional, intent(in) :: zero_zeros !< If present and true, convert negative zeros
!! into ordinary signless zeros.
logical :: unsign_zeros ! If true, convert negative zeros into ordinary signless zeros.
integer :: is, ie, js, je, i, j

unsign_zeros = .false. ; if (present(zero_zeros)) unsign_zeros = zero_zeros

if (scale == 1.0) return
if ((scale == 1.0) .and. (.not.unsign_zeros)) return

call get_simple_array_i_ind(domain, size(array,1), is, ie)
call get_simple_array_j_ind(domain, size(array,2), js, je)
array(is:ie,js:je) = scale*array(is:ie,js:je)
if (scale /= 1.0) &
array(is:ie,js:je) = scale*array(is:ie,js:je)

if (unsign_zeros) then ! Convert negative zeros into zeros
do j=js,je ; do i=is,ie
if (array(i,j) == 0.0) array(i,j) = 0.0
enddo ; enddo
endif

end subroutine rescale_comp_data_2d

Expand Down
60 changes: 48 additions & 12 deletions config_src/infra/FMS2/MOM_domain_infra.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1258,53 +1258,89 @@ end subroutine redistribute_array_4d


!> Rescale the values of a 4-D array in its computational domain by a constant factor
subroutine rescale_comp_data_4d(domain, array, scale)
subroutine rescale_comp_data_4d(domain, array, scale, zero_zeros)
type(MOM_domain_type), intent(in) :: domain !< MOM domain from which to extract information
real, dimension(:,:,:,:), intent(inout) :: array !< The array which is having the data in its
!! computational domain rescaled
real, intent(in) :: scale !< A scaling factor by which to multiply the
!! values in the computational domain of array
integer :: is, ie, js, je
logical, optional, intent(in) :: zero_zeros !< If present and true, convert negative zeros
!! into ordinary signless zeros.
logical :: unsign_zeros ! If true, convert negative zeros into ordinary signless zeros.
integer :: is, ie, js, je, i, j, k, m

if (scale == 1.0) return
unsign_zeros = .false. ; if (present(zero_zeros)) unsign_zeros = zero_zeros

if ((scale == 1.0) .and. (.not.unsign_zeros)) return

call get_simple_array_i_ind(domain, size(array,1), is, ie)
call get_simple_array_j_ind(domain, size(array,2), js, je)
array(is:ie,js:je,:,:) = scale*array(is:ie,js:je,:,:)
if (scale /= 1.0) &
array(is:ie,js:je,:,:) = scale*array(is:ie,js:je,:,:)

if (unsign_zeros) then ! Convert negative zeros into zeros
do m=1,size(array,4) ; do k=1,size(array,3) ; do j=js,je ; do i=is,ie
if (array(i,j,k,m) == 0.0) array(i,j,k,m) = 0.0
enddo ; enddo ; enddo ; enddo
endif

end subroutine rescale_comp_data_4d

!> Rescale the values of a 3-D array in its computational domain by a constant factor
subroutine rescale_comp_data_3d(domain, array, scale)
subroutine rescale_comp_data_3d(domain, array, scale, zero_zeros)
type(MOM_domain_type), intent(in) :: domain !< MOM domain from which to extract information
real, dimension(:,:,:), intent(inout) :: array !< The array which is having the data in its
!! computational domain rescaled
real, intent(in) :: scale !< A scaling factor by which to multiply the
!! values in the computational domain of array
integer :: is, ie, js, je
logical, optional, intent(in) :: zero_zeros !< If present and true, convert negative zeros
!! into ordinary signless zeros.
logical :: unsign_zeros ! If true, convert negative zeros into ordinary signless zeros.
integer :: is, ie, js, je, i, j, k

if (scale == 1.0) return
unsign_zeros = .false. ; if (present(zero_zeros)) unsign_zeros = zero_zeros

if ((scale == 1.0) .and. (.not.unsign_zeros)) return

call get_simple_array_i_ind(domain, size(array,1), is, ie)
call get_simple_array_j_ind(domain, size(array,2), js, je)
array(is:ie,js:je,:) = scale*array(is:ie,js:je,:)
if (scale /= 1.0) &
array(is:ie,js:je,:) = scale*array(is:ie,js:je,:)

if (unsign_zeros) then ! Convert negative zeros into zeros
do k=1,size(array,3) ; do j=js,je ; do i=is,ie
if (array(i,j,k) == 0.0) array(i,j,k) = 0.0
enddo ; enddo ; enddo
endif

end subroutine rescale_comp_data_3d

!> Rescale the values of a 2-D array in its computational domain by a constant factor
subroutine rescale_comp_data_2d(domain, array, scale)
subroutine rescale_comp_data_2d(domain, array, scale, zero_zeros)
type(MOM_domain_type), intent(in) :: domain !< MOM domain from which to extract information
real, dimension(:,:), intent(inout) :: array !< The array which is having the data in its
!! computational domain rescaled
real, intent(in) :: scale !< A scaling factor by which to multiply the
!! values in the computational domain of array
integer :: is, ie, js, je
logical, optional, intent(in) :: zero_zeros !< If present and true, convert negative zeros
!! into ordinary signless zeros.
logical :: unsign_zeros ! If true, convert negative zeros into ordinary signless zeros.
integer :: is, ie, js, je, i, j

unsign_zeros = .false. ; if (present(zero_zeros)) unsign_zeros = zero_zeros

if (scale == 1.0) return
if ((scale == 1.0) .and. (.not.unsign_zeros)) return

call get_simple_array_i_ind(domain, size(array,1), is, ie)
call get_simple_array_j_ind(domain, size(array,2), js, je)
array(is:ie,js:je) = scale*array(is:ie,js:je)
if (scale /= 1.0) &
array(is:ie,js:je) = scale*array(is:ie,js:je)

if (unsign_zeros) then ! Convert negative zeros into zeros
do j=js,je ; do i=is,ie
if (array(i,j) == 0.0) array(i,j) = 0.0
enddo ; enddo
endif

end subroutine rescale_comp_data_2d

Expand Down
Loading

0 comments on commit 9aaf5e1

Please sign in to comment.