Skip to content

Commit

Permalink
(*)non-Boussinesq Z unit update_OBC_segment_data
Browse files Browse the repository at this point in the history
  Revised the update_OBC_segment_data code to keep the z-space input data in
height units ([Z ~> m]) rather than rescaling them to thickness units.  This
change means that the non-Boussinesq open boundary condition calculations avoid
using the Boussinesq reference density.  Associated with this change, 5 internal
variables in update_OBC_segment_data were renamed to reflect that they are layer
vertical extents instead of thicknesses.  Answers are bitwise identical in any
Boussinesq cases.  However, answers will change in any non-Boussinesq cases that
use open boundary conditions that use time_interp_extrnal to read in Z-space
data.
  • Loading branch information
Hallberg-NOAA committed Jan 24, 2024
1 parent d7d126a commit 726e9b0
Showing 1 changed file with 50 additions and 51 deletions.
101 changes: 50 additions & 51 deletions src/core/MOM_open_boundary.F90
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ module MOM_open_boundary
!! have the same units as the field they are being applied to?
integer :: nk_src !< Number of vertical levels in the source data
real, allocatable :: dz_src(:,:,:) !< vertical grid cell spacing of the incoming segment
!! data, set in [Z ~> m] then scaled to [H ~> m or kg m-2]
!! data in [Z ~> m].
real, allocatable :: buffer_dst(:,:,:) !< buffer src data remapped to the target vertical grid.
!! The values for tracers should have the same units as the field
!! they are being applied to?
Expand Down Expand Up @@ -3791,7 +3791,7 @@ subroutine open_boundary_test_extern_h(G, GV, OBC, h)

if (.not. associated(OBC)) return

silly_h = GV%Z_to_H * OBC%silly_h
silly_h = GV%Z_to_H * OBC%silly_h ! This rescaling is here because GV was initialized after OBC.

Check warning on line 3794 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L3794

Added line #L3794 was not covered by tests

do n = 1, OBC%number_of_segments
do k = 1, GV%ke
Expand Down Expand Up @@ -3844,18 +3844,18 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
integer :: ishift, jshift ! offsets for staggered locations
real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: dz ! Distance between the interfaces around a layer [Z ~> m]
real, dimension(:,:,:), allocatable, target :: tmp_buffer ! A buffer for input data [various units]
real, dimension(:), allocatable :: h_stack ! Thicknesses at corner points [H ~> m or kg m-2]
real, dimension(:), allocatable :: dz_stack ! Distance between the interfaces at corner points [Z ~> m]
integer :: is_obc2, js_obc2
integer :: i_seg_offset, j_seg_offset
real :: net_H_src ! Total thickness of the incoming flow in the source field [H ~> m or kg m-2]
real :: net_H_int ! Total thickness of the incoming flow in the model [H ~> m or kg m-2]
real :: net_dz_src ! Total vertical extent of the incoming flow in the source field [Z ~> m]
real :: net_dz_int ! Total vertical extent of the incoming flow in the model [Z ~> m]
real :: scl_fac ! A scaling factor to compensate for differences in total thicknesses [nondim]
real :: tidal_vel ! Interpolated tidal velocity at the OBC points [L T-1 ~> m s-1]
real :: tidal_elev ! Interpolated tidal elevation at the OBC points [Z ~> m]
real, allocatable :: normal_trans_bt(:,:) ! barotropic transport [H L2 T-1 ~> m3 s-1]
integer :: turns ! Number of index quarter turns
real :: time_delta ! Time since tidal reference date [T ~> s]
real :: h_neglect, h_neglect_edge ! Small thicknesses [H ~> m or kg m-2]
real :: dz_neglect, dz_neglect_edge ! Small thicknesses [Z ~> m]

is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec
isd = G%isd ; ied = G%ied ; jsd = G%jsd ; jed = G%jed
Expand All @@ -3869,11 +3869,13 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
if (OBC%add_tide_constituents) time_delta = US%s_to_T * time_type_to_real(Time - OBC%time_ref)

if (OBC%remap_answer_date >= 20190101) then
h_neglect = GV%H_subroundoff ; h_neglect_edge = GV%H_subroundoff
dz_neglect = GV%dZ_subroundoff ; dz_neglect_edge = GV%dZ_subroundoff
elseif (GV%Boussinesq) then
h_neglect = GV%m_to_H * 1.0e-30 ; h_neglect_edge = GV%m_to_H * 1.0e-10
dz_neglect = US%m_to_Z * 1.0e-30 ; dz_neglect_edge = US%m_to_Z * 1.0e-10
elseif (GV%semi_Boussinesq) then
dz_neglect = GV%kg_m2_to_H*GV%H_to_Z * 1.0e-30 ; dz_neglect_edge = GV%kg_m2_to_H*GV%H_to_Z * 1.0e-10

Check warning on line 3876 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L3874-L3876

Added lines #L3874 - L3876 were not covered by tests
else
h_neglect = GV%kg_m2_to_H * 1.0e-30 ; h_neglect_edge = GV%kg_m2_to_H * 1.0e-10
dz_neglect = GV%dZ_subroundoff ; dz_neglect_edge = GV%dZ_subroundoff

Check warning on line 3878 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L3878

Added line #L3878 was not covered by tests
endif

if (OBC%number_of_segments >= 1) then
Expand Down Expand Up @@ -3937,7 +3939,7 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
enddo
endif

allocate(h_stack(GV%ke), source=0.0)
allocate(dz_stack(GV%ke), source=0.0)
do m = 1,segment%num_fields
!This field may not require a high frequency OBC segment update and might be allowed
!a less frequent update as set by the parameter update_OBC_period_max in MOM.F90.
Expand Down Expand Up @@ -4149,6 +4151,7 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
endif
endif

! The units of ...%dz_src are no longer changed from [Z ~> m] to [H ~> m or kg m-2] here.
call adjustSegmentEtaToFitBathymetry(G,GV,US,segment,m)

if (segment%is_E_or_W) then
Expand All @@ -4162,26 +4165,26 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
! Pretty sure we need to check for source/target grid consistency here
segment%field(m)%buffer_dst(I,J,:)=0.0 ! initialize remap destination buffer
if (G%mask2dCu(I,j)>0. .and. G%mask2dCu(I,j+1)>0.) then
h_stack(:) = 0.5*(h(i+ishift,j,:) + h(i+ishift,j+1,:))
dz_stack(:) = 0.5*(dz(i+ishift,j,:) + dz(i+ishift,j+1,:))

Check warning on line 4168 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4168

Added line #L4168 was not covered by tests
call remapping_core_h(OBC%remap_CS, &
segment%field(m)%nk_src,segment%field(m)%dz_src(I,J,:), &
segment%field(m)%nk_src, segment%field(m)%dz_src(I,J,:), &
segment%field(m)%buffer_src(I,J,:), &
GV%ke, h_stack, segment%field(m)%buffer_dst(I,J,:), &
h_neglect, h_neglect_edge)
GV%ke, dz_stack, segment%field(m)%buffer_dst(I,J,:), &
dz_neglect, dz_neglect_edge)

Check warning on line 4173 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4173

Added line #L4173 was not covered by tests
elseif (G%mask2dCu(I,j)>0.) then
h_stack(:) = h(i+ishift,j,:)
dz_stack(:) = dz(i+ishift,j,:)

Check warning on line 4175 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4175

Added line #L4175 was not covered by tests
call remapping_core_h(OBC%remap_CS, &
segment%field(m)%nk_src,segment%field(m)%dz_src(I,J,:), &
segment%field(m)%nk_src, segment%field(m)%dz_src(I,J,:), &
segment%field(m)%buffer_src(I,J,:), &
GV%ke, h_stack, segment%field(m)%buffer_dst(I,J,:), &
h_neglect, h_neglect_edge)
GV%ke, dz_stack, segment%field(m)%buffer_dst(I,J,:), &
dz_neglect, dz_neglect_edge)

Check warning on line 4180 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4180

Added line #L4180 was not covered by tests
elseif (G%mask2dCu(I,j+1)>0.) then
h_stack(:) = h(i+ishift,j+1,:)
dz_stack(:) = dz(i+ishift,j+1,:)

Check warning on line 4182 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4182

Added line #L4182 was not covered by tests
call remapping_core_h(OBC%remap_CS, &
segment%field(m)%nk_src,segment%field(m)%dz_src(I,j,:), &
segment%field(m)%nk_src, segment%field(m)%dz_src(I,j,:), &
segment%field(m)%buffer_src(I,J,:), &
GV%ke, h_stack, segment%field(m)%buffer_dst(I,J,:), &
h_neglect, h_neglect_edge)
GV%ke, dz_stack, segment%field(m)%buffer_dst(I,J,:), &
dz_neglect, dz_neglect_edge)

Check warning on line 4187 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4187

Added line #L4187 was not covered by tests
endif
enddo
else
Expand All @@ -4190,14 +4193,14 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
! Pretty sure we need to check for source/target grid consistency here
segment%field(m)%buffer_dst(I,j,:)=0.0 ! initialize remap destination buffer
if (G%mask2dCu(I,j)>0.) then
net_H_src = sum( segment%field(m)%dz_src(I,j,:) )
net_H_int = sum( h(i+ishift,j,:) )
scl_fac = net_H_int / net_H_src
net_dz_src = sum( segment%field(m)%dz_src(I,j,:) )
net_dz_int = sum( dz(i+ishift,j,:) )
scl_fac = net_dz_int / net_dz_src

Check warning on line 4198 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4196-L4198

Added lines #L4196 - L4198 were not covered by tests
call remapping_core_h(OBC%remap_CS, &
segment%field(m)%nk_src, scl_fac*segment%field(m)%dz_src(I,j,:), &
segment%field(m)%nk_src, scl_fac*segment%field(m)%dz_src(I,j,:), &
segment%field(m)%buffer_src(I,j,:), &
GV%ke, h(i+ishift,j,:), segment%field(m)%buffer_dst(I,j,:), &
h_neglect, h_neglect_edge)
GV%ke, dz(i+ishift,j,:), segment%field(m)%buffer_dst(I,j,:), &
dz_neglect, dz_neglect_edge)

Check warning on line 4203 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4203

Added line #L4203 was not covered by tests
endif
enddo
endif
Expand All @@ -4212,26 +4215,26 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
if (G%mask2dCv(i,J)>0. .and. G%mask2dCv(i+1,J)>0.) then
! Using the h remapping approach
! Pretty sure we need to check for source/target grid consistency here
h_stack(:) = 0.5*(h(i,j+jshift,:) + h(i+1,j+jshift,:))
dz_stack(:) = 0.5*(dz(i,j+jshift,:) + dz(i+1,j+jshift,:))

Check warning on line 4218 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4218

Added line #L4218 was not covered by tests
call remapping_core_h(OBC%remap_CS, &
segment%field(m)%nk_src,segment%field(m)%dz_src(I,J,:), &
segment%field(m)%nk_src, segment%field(m)%dz_src(I,J,:), &
segment%field(m)%buffer_src(I,J,:), &
GV%ke, h_stack, segment%field(m)%buffer_dst(I,J,:), &
h_neglect, h_neglect_edge)
GV%ke, dz_stack, segment%field(m)%buffer_dst(I,J,:), &
dz_neglect, dz_neglect_edge)

Check warning on line 4223 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4223

Added line #L4223 was not covered by tests
elseif (G%mask2dCv(i,J)>0.) then
h_stack(:) = h(i,j+jshift,:)
dz_stack(:) = dz(i,j+jshift,:)

Check warning on line 4225 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4225

Added line #L4225 was not covered by tests
call remapping_core_h(OBC%remap_CS, &
segment%field(m)%nk_src,segment%field(m)%dz_src(I,J,:), &
segment%field(m)%nk_src, segment%field(m)%dz_src(I,J,:), &
segment%field(m)%buffer_src(I,J,:), &
GV%ke, h_stack, segment%field(m)%buffer_dst(I,J,:), &
h_neglect, h_neglect_edge)
GV%ke, dz_stack, segment%field(m)%buffer_dst(I,J,:), &
dz_neglect, dz_neglect_edge)

Check warning on line 4230 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4230

Added line #L4230 was not covered by tests
elseif (G%mask2dCv(i+1,J)>0.) then
h_stack(:) = h(i+1,j+jshift,:)
dz_stack(:) = dz(i+1,j+jshift,:)

Check warning on line 4232 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4232

Added line #L4232 was not covered by tests
call remapping_core_h(OBC%remap_CS, &
segment%field(m)%nk_src,segment%field(m)%dz_src(I,J,:), &
segment%field(m)%nk_src, segment%field(m)%dz_src(I,J,:), &
segment%field(m)%buffer_src(I,J,:), &
GV%ke, h_stack, segment%field(m)%buffer_dst(I,J,:), &
h_neglect, h_neglect_edge)
GV%ke, dz_stack, segment%field(m)%buffer_dst(I,J,:), &
dz_neglect, dz_neglect_edge)

Check warning on line 4237 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4237

Added line #L4237 was not covered by tests
endif
enddo
else
Expand All @@ -4240,14 +4243,14 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
! Pretty sure we need to check for source/target grid consistency here
segment%field(m)%buffer_dst(i,J,:)=0.0 ! initialize remap destination buffer
if (G%mask2dCv(i,J)>0.) then
net_H_src = sum( segment%field(m)%dz_src(i,J,:) )
net_H_int = sum( h(i,j+jshift,:) )
scl_fac = net_H_int / net_H_src
net_dz_src = sum( segment%field(m)%dz_src(i,J,:) )
net_dz_int = sum( dz(i,j+jshift,:) )
scl_fac = net_dz_int / net_dz_src

Check warning on line 4248 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4246-L4248

Added lines #L4246 - L4248 were not covered by tests
call remapping_core_h(OBC%remap_CS, &
segment%field(m)%nk_src, scl_fac*segment%field(m)%dz_src(i,J,:), &
segment%field(m)%nk_src, scl_fac* segment%field(m)%dz_src(i,J,:), &
segment%field(m)%buffer_src(i,J,:), &
GV%ke, h(i,j+jshift,:), segment%field(m)%buffer_dst(i,J,:), &
h_neglect, h_neglect_edge)
GV%ke, dz(i,j+jshift,:), segment%field(m)%buffer_dst(i,J,:), &
dz_neglect, dz_neglect_edge)

Check warning on line 4253 in src/core/MOM_open_boundary.F90

View check run for this annotation

Codecov / codecov/patch

src/core/MOM_open_boundary.F90#L4253

Added line #L4253 was not covered by tests
endif
enddo
endif
Expand Down Expand Up @@ -4516,7 +4519,7 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
endif

enddo ! end field loop
deallocate(h_stack)
deallocate(dz_stack)
deallocate(normal_trans_bt)

enddo ! end segment loop
Expand Down Expand Up @@ -5750,10 +5753,6 @@ subroutine adjustSegmentEtaToFitBathymetry(G, GV, US, segment,fld)
! endif
!do k=nz,2,-1 ; eta(i,j,K) = eta(i,j,K+1) + segment%field(fld)%dz_src(i,j,k) ; enddo
endif
! Now convert thicknesses to units of H.
do k=1,nz
segment%field(fld)%dz_src(i,j,k) = segment%field(fld)%dz_src(i,j,k)*GV%Z_to_H
enddo
enddo ; enddo

! can not do communication call here since only PEs on the current segment are here
Expand Down

0 comments on commit 726e9b0

Please sign in to comment.