Skip to content

Commit 6801f61

Browse files
Hallberg-NOAAmarshallward
authored andcommitted
(*)Fix northern Flather OBCs in southern halos
Added additional logic to avoid segmentation faults from applying Flather open boundary conditions near the opposite side of the computational domain (e.g., applying a Northern Flather boundary condition on the southern edge of the domain). This situation does not arise when open boundaries are only found on the edges of a domain, but in parallel cases with sloped OBCs (such as the ESMG-configs rotated seamount test case) this atypical situation can arise. The key point to the specific fix is to note that when such a case arises, the OBC velocity in the outer halo point does not subsequently impact the solution on that PE either because its effects are masked out by land or OBC points at the neighboring orthogonal velocities, and then they are overwritten by a halo update (perhaps several steps later). All answers are bitwise identical in all cases that have been tested and were working before, and the ESMG/rotated_seamount test case is now running correctly (and giving identical answers) for a variety of PE counts.
1 parent 4c2db8b commit 6801f61

1 file changed

Lines changed: 51 additions & 14 deletions

File tree

src/core/MOM_barotropic.F90

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3686,7 +3686,11 @@ subroutine apply_u_velocity_OBCs(ubt, uhbt, ubt_trans, eta, SpV_avg, ubt_old, BT
36863686
elseif (BT_OBC%u_OBC_type(I,j) == FLATHER_OBC) then ! Eastern Flather OBC
36873687
cfl = dtbt * BT_OBC%Cg_u(I,j) * G%IdxCu(I,j) ! CFL
36883688
u_inlet = cfl*ubt_old(I-1,j) + (1.0-cfl)*ubt_old(I,j) ! Valid for cfl<1
3689-
if (GV%Boussinesq) then
3689+
if (I <= MS%isdw) then
3690+
! Do not apply an Eastern Flather OBC at the western halo points on a PE, as doing so would
3691+
! create a segmentation fault and this velocity will not propagate through to the next iteration.
3692+
ssh_in = BT_OBC%SSH_outer_u(I,j)
3693+
elseif (GV%Boussinesq) then
36903694
ssh_in = GV%H_to_Z*(eta(i,j) + (0.5-cfl)*(eta(i,j)-eta(i-1,j))) ! internal
36913695
else
36923696
ssh_1 = GV%H_to_RZ * eta(i,j) * SpV_avg(i,j) - (CS%bathyT(i,j) + G%Z_ref)
@@ -3739,7 +3743,11 @@ subroutine apply_u_velocity_OBCs(ubt, uhbt, ubt_trans, eta, SpV_avg, ubt_old, BT
37393743
elseif (BT_OBC%u_OBC_type(I,j) == -FLATHER_OBC) then ! Western Flather OBC
37403744
cfl = dtbt * BT_OBC%Cg_u(I,j) * G%IdxCu(I,j) ! CFL
37413745
u_inlet = cfl*ubt_old(I+1,j) + (1.0-cfl)*ubt_old(I,j) ! Valid for cfl<1
3742-
if (GV%Boussinesq) then
3746+
if (I >= MS%iedw-1) then
3747+
! Do not apply a Western Flather OBC at the eastern halo points on a PE, as doing so would
3748+
! create a segmentation fault and this velocity will not propagate through to the next iteration.
3749+
ssh_in = BT_OBC%SSH_outer_u(I,j)
3750+
elseif (GV%Boussinesq) then
37433751
ssh_in = GV%H_to_Z*(eta(i+1,j) + (0.5-cfl)*(eta(i+1,j)-eta(i+2,j))) ! internal
37443752
else
37453753
ssh_1 = GV%H_to_RZ * eta(i+1,j) * SpV_avg(i+1,j) - (CS%bathyT(i+1,j) + G%Z_ref)
@@ -3872,7 +3880,11 @@ subroutine apply_v_velocity_OBCs(vbt, vhbt, vbt_trans, eta, SpV_avg, vbt_old, BT
38723880
elseif (BT_OBC%v_OBC_type(i,J) == FLATHER_OBC) then ! Northern Flather OBC
38733881
cfl = dtbt * BT_OBC%Cg_v(i,J) * G%IdyCv(i,J) ! CFL
38743882
v_inlet = cfl*vbt_old(i,J-1) + (1.0-cfl)*vbt_old(i,J) ! Valid for cfl<1
3875-
if (GV%Boussinesq) then
3883+
if (J <= MS%jsdw) then
3884+
! Do not apply a Northern Flather OBC at the southern halo points on a PE, as doing so would
3885+
! create a segmentation fault and this velocity will not propagate through to the next iteration.
3886+
ssh_in = BT_OBC%SSH_outer_v(i,J)
3887+
elseif (GV%Boussinesq) then
38763888
ssh_in = GV%H_to_Z*(eta(i,j) + (0.5-cfl)*(eta(i,j)-eta(i,j-1))) ! internal
38773889
else
38783890
ssh_1 = GV%H_to_RZ * eta(i,j) * SpV_avg(i,j) - (CS%bathyT(i,j) + G%Z_ref)
@@ -3926,7 +3938,11 @@ subroutine apply_v_velocity_OBCs(vbt, vhbt, vbt_trans, eta, SpV_avg, vbt_old, BT
39263938
elseif (BT_OBC%v_OBC_type(i,J) == -FLATHER_OBC) then ! Southern Flather OBC
39273939
cfl = dtbt * BT_OBC%Cg_v(i,J) * G%IdyCv(i,J) ! CFL
39283940
v_inlet = cfl*vbt_old(i,J+1) + (1.0-cfl)*vbt_old(i,J) ! Valid for cfl <1
3929-
if (GV%Boussinesq) then
3941+
if (J >= MS%jedw-1) then
3942+
! Do not apply a Southern Flather OBC at the northern halo points on a PE, as doing so would
3943+
! create a segmentation fault and this velocity will not propagate through to the next iteration.
3944+
ssh_in = BT_OBC%SSH_outer_v(i,J)
3945+
elseif (GV%Boussinesq) then
39303946
ssh_in = GV%H_to_Z*(eta(i,j+1) + (0.5-cfl)*(eta(i,j+1)-eta(i,j+2))) ! internal
39313947
else
39323948
ssh_1 = GV%H_to_RZ * eta(i,j+1) * SpV_avg(i,j+1) - (CS%bathyT(i,j+1) + G%Z_ref)
@@ -3987,7 +4003,7 @@ subroutine initialize_BT_OBC(OBC, BT_OBC, G, CS)
39874003
real :: OBC_sign ! A sign encoding the direction of the OBC being used at a point [nondim]
39884004
real :: OBC_type ! A real copy of the integer encoding the type of OBC being used at a point [nondim]
39894005
integer :: i, j, isdw, iedw, jsdw, jedw
3990-
integer :: l_seg
4006+
integer :: l_seg, Flather_OBC_in_halo
39914007

39924008
isdw = CS%isdw ; iedw = CS%iedw ; jsdw = CS%jsdw ; jedw = CS%jedw
39934009

@@ -4037,27 +4053,48 @@ subroutine initialize_BT_OBC(OBC, BT_OBC, G, CS)
40374053
BT_OBC%is_v_N_obc = iedw + 1 ; BT_OBC%ie_v_N_obc = isdw - 1
40384054
BT_OBC%Js_v_N_obc = jedw + 1 ; BT_OBC%Je_v_N_obc = jsdw - 2
40394055

4056+
Flather_OBC_in_halo = 0
40404057
do j=jsdw,jedw ; do I=isdw-1,iedw
40414058
BT_OBC%u_OBC_type(I,j) = nint(u_OBC(I,j))
40424059
if (BT_OBC%u_OBC_type(I,j) < 0) then ! This point has OBC_DIRECTION_W.
4043-
BT_OBC%Is_u_W_obc = min(I, BT_OBC%Is_u_W_obc) ; BT_OBC%Ie_u_W_obc = max(I, BT_OBC%Ie_u_W_obc)
4044-
BT_OBC%js_u_W_obc = min(j, BT_OBC%js_u_W_obc) ; BT_OBC%je_u_W_obc = max(j, BT_OBC%je_u_W_obc)
4060+
if ((BT_OBC%u_OBC_type(I,j) == -FLATHER_OBC) .and. (I >= iedw-1)) then
4061+
! There is no need to specify the OBC at this point, but the stencil might need to be increased.
4062+
Flather_OBC_in_halo = 1
4063+
else
4064+
BT_OBC%Is_u_W_obc = min(I, BT_OBC%Is_u_W_obc) ; BT_OBC%Ie_u_W_obc = max(I, BT_OBC%Ie_u_W_obc)
4065+
BT_OBC%js_u_W_obc = min(j, BT_OBC%js_u_W_obc) ; BT_OBC%je_u_W_obc = max(j, BT_OBC%je_u_W_obc)
4066+
endif
40454067
endif
40464068
if (BT_OBC%u_OBC_type(I,j) > 0) then ! This point has OBC_DIRECTION_E.
4047-
BT_OBC%Is_u_E_obc = min(I, BT_OBC%Is_u_E_obc) ; BT_OBC%Ie_u_E_obc = max(I, BT_OBC%Ie_u_E_obc)
4048-
BT_OBC%js_u_E_obc = min(j, BT_OBC%js_u_E_obc) ; BT_OBC%je_u_E_obc = max(j, BT_OBC%je_u_E_obc)
4069+
if ((BT_OBC%u_OBC_type(I,j) == FLATHER_OBC) .and. (I <= isdw)) then
4070+
! There is no need to specify the OBC at this point, but the stencil might need to be increased.
4071+
Flather_OBC_in_halo = 1
4072+
else
4073+
BT_OBC%Is_u_E_obc = min(I, BT_OBC%Is_u_E_obc) ; BT_OBC%Ie_u_E_obc = max(I, BT_OBC%Ie_u_E_obc)
4074+
BT_OBC%js_u_E_obc = min(j, BT_OBC%js_u_E_obc) ; BT_OBC%je_u_E_obc = max(j, BT_OBC%je_u_E_obc)
4075+
endif
40494076
endif
40504077
enddo ; enddo
40514078

40524079
do J=jsdw-1,jedw ; do i=isdw,iedw
40534080
BT_OBC%v_OBC_type(i,J) = nint(v_OBC(i,J))
4054-
if (BT_OBC%v_OBC_type(i,J) < 0) then ! This point has OBC_DIRECTION_S.
4055-
BT_OBC%is_v_S_obc = min(i, BT_OBC%is_v_S_obc) ; BT_OBC%ie_v_S_obc = max(i, BT_OBC%ie_v_S_obc)
4056-
BT_OBC%Js_v_S_obc = min(J, BT_OBC%Js_v_S_obc) ; BT_OBC%Je_v_S_obc = max(J, BT_OBC%Je_v_S_obc)
4081+
if (BT_OBC%v_OBC_type(i,J) < 0) then ! This point has OBC_DIRECTION_S.
4082+
if ((BT_OBC%v_OBC_type(i,J) == -FLATHER_OBC) .and. (J >= jedw-1)) then
4083+
! There is no need to specify the OBC at this point, but the stencil might need to be increased.
4084+
Flather_OBC_in_halo = 1
4085+
else
4086+
BT_OBC%is_v_S_obc = min(i, BT_OBC%is_v_S_obc) ; BT_OBC%ie_v_S_obc = max(i, BT_OBC%ie_v_S_obc)
4087+
BT_OBC%Js_v_S_obc = min(J, BT_OBC%Js_v_S_obc) ; BT_OBC%Je_v_S_obc = max(J, BT_OBC%Je_v_S_obc)
4088+
endif
40574089
endif
40584090
if (BT_OBC%v_OBC_type(i,J) > 0) then ! This point has OBC_DIRECTION_N.
4059-
BT_OBC%is_v_N_obc = min(i, BT_OBC%is_v_N_obc) ; BT_OBC%ie_v_N_obc = max(i, BT_OBC%ie_v_N_obc)
4060-
BT_OBC%Js_v_N_obc = min(J, BT_OBC%Js_v_N_obc) ; BT_OBC%Je_v_N_obc = max(J, BT_OBC%Je_v_N_obc)
4091+
if ((BT_OBC%v_OBC_type(i,J) == FLATHER_OBC) .and. (J <= jsdw)) then
4092+
! There is no need to specify the OBC at this point, but the stencil might need to be increased.
4093+
Flather_OBC_in_halo = 1
4094+
else
4095+
BT_OBC%is_v_N_obc = min(i, BT_OBC%is_v_N_obc) ; BT_OBC%ie_v_N_obc = max(i, BT_OBC%ie_v_N_obc)
4096+
BT_OBC%Js_v_N_obc = min(J, BT_OBC%Js_v_N_obc) ; BT_OBC%Je_v_N_obc = max(J, BT_OBC%Je_v_N_obc)
4097+
endif
40614098
endif
40624099
enddo ; enddo
40634100

0 commit comments

Comments
 (0)