From 6f35d66d2fdaf851837318251771a36b2d75427b Mon Sep 17 00:00:00 2001 From: Kate Hedstrom Date: Wed, 30 Oct 2024 12:16:21 -0800 Subject: [PATCH 01/11] Fix for MASK_OUTSIDE_OBCS with MASKING_DEPTH --- src/core/MOM_open_boundary.F90 | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/core/MOM_open_boundary.F90 b/src/core/MOM_open_boundary.F90 index 797f60bd9b..a578729d5c 100644 --- a/src/core/MOM_open_boundary.F90 +++ b/src/core/MOM_open_boundary.F90 @@ -5061,7 +5061,9 @@ subroutine mask_outside_OBCs(G, US, param_file, OBC) integer :: i, j integer :: l_seg logical :: fatal_error = .False. - real :: min_depth ! The minimum depth for ocean points [Z ~> m] + real :: min_depth ! The minimum depth for ocean points [Z ~> m] + real :: mask_depth ! The masking depth for ocean points [Z ~> m] + real :: Dmask ! The depth for masking in the same units as G%bathyT [Z ~> m]. integer, parameter :: cin = 3, cout = 4, cland = -1, cedge = -2 character(len=256) :: mesg ! Message for error messages. real, allocatable, dimension(:,:) :: color, color2 ! For sorting inside from outside, @@ -5071,6 +5073,12 @@ subroutine mask_outside_OBCs(G, US, param_file, OBC) call get_param(param_file, mdl, "MINIMUM_DEPTH", min_depth, & units="m", default=0.0, scale=US%m_to_Z, do_not_log=.true.) + call get_param(param_file, mdl, "MASKING_DEPTH", mask_depth, & + units="m", default=-9999.0, scale=US%m_to_Z, do_not_log=.true.) + + Dmask = mask_depth + if (mask_depth == -9999.0*US%m_to_Z) Dmask = min_depth + ! The reference depth on a dyn_horgrid is 0, otherwise would need: min_depth = min_depth - G%Z_ref allocate(color(G%isd:G%ied, G%jsd:G%jed), source=0.0) @@ -5161,7 +5169,7 @@ subroutine mask_outside_OBCs(G, US, param_file, OBC) &"the masking of the outside grid points.")') i, j call MOM_error(WARNING,"MOM mask_outside_OBCs: "//mesg, all_print=.true.) endif - if (color(i,j) == cout) G%bathyT(i,j) = min_depth + if (color(i,j) == cout) G%bathyT(i,j) = Dmask enddo ; enddo if (fatal_error) call MOM_error(FATAL, & "MOM_open_boundary: inconsistent OBC segments.") From c68540e5ad263e724f0bdaff7ba77e8aac49afa2 Mon Sep 17 00:00:00 2001 From: Kate Hedstrom Date: Wed, 6 Nov 2024 15:25:49 -0900 Subject: [PATCH 02/11] Fix the tracer advection outside of interior OBCs. - Otherwise, the tracer values just outside the OBC get updated based on fluxes at the OBC and quickly go out of bounds of the equation of state. --- src/tracer/MOM_tracer_advect.F90 | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/tracer/MOM_tracer_advect.F90 b/src/tracer/MOM_tracer_advect.F90 index 0e129b2d03..175006b556 100644 --- a/src/tracer/MOM_tracer_advect.F90 +++ b/src/tracer/MOM_tracer_advect.F90 @@ -648,6 +648,19 @@ subroutine advect_x(Tr, hprev, uhr, uh_neglect, OBC, domore_u, ntr, Idt, & endif enddo + ! Update do_i so that nothing changes outside of the OBC (problem for interior OBCs only) + if (associated(OBC)) then ; if (OBC%OBC_pe) then + if (OBC%specified_u_BCs_exist_globally .or. OBC%open_u_BCs_exist_globally) then + do i=is,ie-1 ; if (OBC%segnum_u(I,j) /= OBC_NONE) then + if (OBC%segment(OBC%segnum_u(I,j))%direction == OBC_DIRECTION_E) then + do_i(i+1,j) = .false. + elseif (OBC%segment(OBC%segnum_u(I,j))%direction == OBC_DIRECTION_W) then + do_i(i,j) = .false. + endif + endif ; enddo + endif + endif ; endif + ! update tracer concentration from i-flux and save some diagnostics do m=1,ntr @@ -1039,6 +1052,19 @@ subroutine advect_y(Tr, hprev, vhr, vh_neglect, OBC, domore_v, ntr, Idt, & else ; do_i(i,j) = .false. ; endif enddo + ! Update do_i so that nothing changes outside of the OBC (problem for interior OBCs only) + if (associated(OBC)) then ; if (OBC%OBC_pe) then + if (OBC%specified_v_BCs_exist_globally .or. OBC%open_v_BCs_exist_globally) then + do i=is,ie-1 ; if (OBC%segnum_v(i,J) /= OBC_NONE) then + if (OBC%segment(OBC%segnum_v(i,J))%direction == OBC_DIRECTION_N) then + do_i(i,j+1) = .false. + elseif (OBC%segment(OBC%segnum_v(i,J))%direction == OBC_DIRECTION_S) then + do_i(i,j) = .false. + endif + endif ; enddo + endif + endif ; endif + ! update tracer and save some diagnostics do m=1,ntr do i=is,ie ; if (do_i(i,j)) then From 0692b9b13735eb9a86f3c5500c1c2717bbb611fd Mon Sep 17 00:00:00 2001 From: Kate Hedstrom Date: Thu, 7 Nov 2024 16:03:09 -0900 Subject: [PATCH 03/11] A more correct fix to tracer advection - The previous version did the wrong thing at northern boundaries, at a southern corner too. --- src/tracer/MOM_tracer_advect.F90 | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/tracer/MOM_tracer_advect.F90 b/src/tracer/MOM_tracer_advect.F90 index 175006b556..e11ee6e5a5 100644 --- a/src/tracer/MOM_tracer_advect.F90 +++ b/src/tracer/MOM_tracer_advect.F90 @@ -1055,13 +1055,18 @@ subroutine advect_y(Tr, hprev, vhr, vh_neglect, OBC, domore_v, ntr, Idt, & ! Update do_i so that nothing changes outside of the OBC (problem for interior OBCs only) if (associated(OBC)) then ; if (OBC%OBC_pe) then if (OBC%specified_v_BCs_exist_globally .or. OBC%open_v_BCs_exist_globally) then - do i=is,ie-1 ; if (OBC%segnum_v(i,J) /= OBC_NONE) then - if (OBC%segment(OBC%segnum_v(i,J))%direction == OBC_DIRECTION_N) then - do_i(i,j+1) = .false. - elseif (OBC%segment(OBC%segnum_v(i,J))%direction == OBC_DIRECTION_S) then - do_i(i,j) = .false. + do i=is,ie + if (OBC%segnum_v(i,J-1) /= OBC_NONE) then + if (OBC%segment(OBC%segnum_v(i,J-1))%direction == OBC_DIRECTION_N) then + do_i(i,j) = .false. + endif endif - endif ; enddo + if (OBC%segnum_v(i,J) /= OBC_NONE) then + if (OBC%segment(OBC%segnum_v(i,J))%direction == OBC_DIRECTION_S) then + do_i(i,j) = .false. + endif + endif + enddo endif endif ; endif From ac162dc275d405d53ee91b9b22936c2186ea0faf Mon Sep 17 00:00:00 2001 From: Kate Hedstrom Date: Fri, 8 Nov 2024 10:09:44 -0900 Subject: [PATCH 04/11] Better fix to eta outside of OBCs issue - It hasn't yet caused a blowup that I know of, but better to prevent any trouble while we're thinking about it. --- src/core/MOM_barotropic.F90 | 40 +++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/core/MOM_barotropic.F90 b/src/core/MOM_barotropic.F90 index 9e2014dc81..fa2cadfa7f 100644 --- a/src/core/MOM_barotropic.F90 +++ b/src/core/MOM_barotropic.F90 @@ -737,6 +737,7 @@ subroutine btstep(U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, forces, pbce, integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB integer :: ioff, joff integer :: l_seg + real :: factor(SZI_(G),SZJ_(G)) ! If non-zero, work on given points. if (.not.CS%module_is_initialized) call MOM_error(FATAL, & "btstep: Module MOM_barotropic must be initialized before it is used.") @@ -2448,17 +2449,52 @@ subroutine btstep(U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, forces, pbce, haloshift=iev-ie, unscale=US%L_to_m**2*GV%H_to_m) endif + do j=jsv,jev + do i=isv,iev + factor(i,j) = CS%IareaT(i,j) + enddo + enddo + + ! Update factor so that nothing changes outside of the OBC (problem for interior OBCs only) + if (associated(OBC)) then ; if (OBC%OBC_pe) then + do j=jsv,jev + if (OBC%specified_u_BCs_exist_globally .or. OBC%open_u_BCs_exist_globally) then + do i=isv,iev-1 ; if (OBC%segnum_u(I,j) /= OBC_NONE) then + if (OBC%segment(OBC%segnum_u(I,j))%direction == OBC_DIRECTION_E) then + factor(i+1,j) = 0.0 + elseif (OBC%segment(OBC%segnum_u(I,j))%direction == OBC_DIRECTION_W) then + factor(i,j) = 0.0 + endif + endif ; enddo + endif + if (OBC%specified_v_BCs_exist_globally .or. OBC%open_v_BCs_exist_globally) then + do i=isv,iev + if (OBC%segnum_v(i,J-1) /= OBC_NONE) then + if (OBC%segment(OBC%segnum_v(i,J-1))%direction == OBC_DIRECTION_N) then + factor(i,j) = 0.0 + endif + endif + if (OBC%segnum_v(i,J) /= OBC_NONE) then + if (OBC%segment(OBC%segnum_v(i,J))%direction == OBC_DIRECTION_S) then + factor(i,j) = 0.0 + endif + endif + enddo + endif + enddo + endif ; endif + if (integral_BT_cont) then !$OMP do do j=jsv,jev ; do i=isv,iev - eta(i,j) = (eta_IC(i,j) + n*eta_src(i,j)) + CS%IareaT(i,j) * & + eta(i,j) = (eta_IC(i,j) + n*eta_src(i,j)) + factor(i,j) * & ((uhbt_int(I-1,j) - uhbt_int(I,j)) + (vhbt_int(i,J-1) - vhbt_int(i,J))) eta_wtd(i,j) = eta_wtd(i,j) + eta(i,j) * wt_eta(n) enddo ; enddo else !$OMP do do j=jsv,jev ; do i=isv,iev - eta(i,j) = (eta(i,j) + eta_src(i,j)) + (dtbt * CS%IareaT(i,j)) * & + eta(i,j) = (eta(i,j) + eta_src(i,j)) + (dtbt * factor(i,j)) * & ((uhbt(I-1,j) - uhbt(I,j)) + (vhbt(i,J-1) - vhbt(i,J))) eta_wtd(i,j) = eta_wtd(i,j) + eta(i,j) * wt_eta(n) enddo ; enddo From 7ee7ad70813e274c97bd3999cb1856376ff602b8 Mon Sep 17 00:00:00 2001 From: Kate Hedstrom Date: Wed, 20 Nov 2024 17:48:32 -0900 Subject: [PATCH 05/11] More tinkering with OBC_in vs CS%OBC --- src/core/MOM.F90 | 20 ++++++++++++ src/core/MOM_open_boundary.F90 | 56 +++++++++++++++++----------------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index ad906fbdb4..3ab558361f 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -2897,6 +2897,26 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, & ! reservoirs are used. call open_boundary_register_restarts(HI, GV, US, CS%OBC, CS%tracer_Reg, & param_file, restart_CSp, use_temperature) + if (turns /= 0) then + if (CS%OBC%radiation_BCs_exist_globally) then + OBC_in%rx_normal => CS%OBC%rx_normal + OBC_in%ry_normal => CS%OBC%ry_normal + endif + if (CS%OBC%oblique_BCs_exist_globally) then + OBC_in%rx_oblique_u => CS%OBC%rx_oblique_u + OBC_in%ry_oblique_u => CS%OBC%ry_oblique_u + OBC_in%rx_oblique_v => CS%OBC%rx_oblique_v + OBC_in%ry_oblique_v => CS%OBC%ry_oblique_v + OBC_in%cff_normal_u => CS%OBC%cff_normal_u + OBC_in%cff_normal_v => CS%OBC%cff_normal_v + endif + if (any(CS%OBC%tracer_x_reservoirs_used)) then + OBC_in%tres_x => CS%OBC%tres_x + endif + if (any(CS%OBC%tracer_y_reservoirs_used)) then + OBC_in%tres_y => CS%OBC%tres_y + endif + endif endif if (present(waves_CSp)) then diff --git a/src/core/MOM_open_boundary.F90 b/src/core/MOM_open_boundary.F90 index a578729d5c..83ff646a24 100644 --- a/src/core/MOM_open_boundary.F90 +++ b/src/core/MOM_open_boundary.F90 @@ -353,24 +353,24 @@ module MOM_open_boundary type(remapping_CS), pointer :: remap_h_CS=> NULL() !< ALE remapping control structure for !! thickness-based fields on segments type(OBC_registry_type), pointer :: OBC_Reg => NULL() !< Registry type for boundaries - real, allocatable :: rx_normal(:,:,:) !< Array storage for normal phase speed for EW radiation OBCs in units of + real, pointer :: rx_normal(:,:,:) !< Array storage for normal phase speed for EW radiation OBCs in units of !! grid points per timestep [nondim] - real, allocatable :: ry_normal(:,:,:) !< Array storage for normal phase speed for NS radiation OBCs in units of + real, pointer :: ry_normal(:,:,:) !< Array storage for normal phase speed for NS radiation OBCs in units of !! grid points per timestep [nondim] - real, allocatable :: rx_oblique_u(:,:,:) !< X-direction oblique boundary condition radiation speeds squared + real, pointer :: rx_oblique_u(:,:,:) !< X-direction oblique boundary condition radiation speeds squared !! at u points for restarts [L2 T-2 ~> m2 s-2] - real, allocatable :: ry_oblique_u(:,:,:) !< Y-direction oblique boundary condition radiation speeds squared + real, pointer :: ry_oblique_u(:,:,:) !< Y-direction oblique boundary condition radiation speeds squared !! at u points for restarts [L2 T-2 ~> m2 s-2] - real, allocatable :: rx_oblique_v(:,:,:) !< X-direction oblique boundary condition radiation speeds squared + real, pointer :: rx_oblique_v(:,:,:) !< X-direction oblique boundary condition radiation speeds squared !! at v points for restarts [L2 T-2 ~> m2 s-2] - real, allocatable :: ry_oblique_v(:,:,:) !< Y-direction oblique boundary condition radiation speeds squared + real, pointer :: ry_oblique_v(:,:,:) !< Y-direction oblique boundary condition radiation speeds squared !! at v points for restarts [L2 T-2 ~> m2 s-2] - real, allocatable :: cff_normal_u(:,:,:) !< Denominator for normalizing EW oblique boundary condition radiation + real, pointer :: cff_normal_u(:,:,:) !< Denominator for normalizing EW oblique boundary condition radiation !! rates at u points for restarts [L2 T-2 ~> m2 s-2] - real, allocatable :: cff_normal_v(:,:,:) !< Denominator for normalizing NS oblique boundary condition radiation + real, pointer :: cff_normal_v(:,:,:) !< Denominator for normalizing NS oblique boundary condition radiation !! rates at v points for restarts [L2 T-2 ~> m2 s-2] - real, allocatable :: tres_x(:,:,:,:) !< Array storage of tracer reservoirs for restarts, in unscaled units [conc] - real, allocatable :: tres_y(:,:,:,:) !< Array storage of tracer reservoirs for restarts, in unscaled units [conc] + real, pointer :: tres_x(:,:,:,:) !< Array storage of tracer reservoirs for restarts, in unscaled units [conc] + real, pointer :: tres_y(:,:,:,:) !< Array storage of tracer reservoirs for restarts, in unscaled units [conc] logical :: debug !< If true, write verbose checksums for debugging purposes. real :: silly_h !< A silly value of thickness outside of the domain that can be used to test !! the independence of the OBCs to this external data [Z ~> m]. @@ -1956,15 +1956,15 @@ subroutine open_boundary_init(G, GV, US, param_file, OBC, restart_CS) call create_group_pass(OBC%pass_oblique, OBC%cff_normal_u, OBC%cff_normal_v, G%Domain, To_All+Scalar_Pair) call do_group_pass(OBC%pass_oblique, G%Domain) endif - if (allocated(OBC%tres_x) .and. allocated(OBC%tres_y)) then + if (associated(OBC%tres_x) .and. associated(OBC%tres_y)) then do m=1,OBC%ntr call pass_vector(OBC%tres_x(:,:,:,m), OBC%tres_y(:,:,:,m), G%Domain, To_All+Scalar_Pair) enddo - elseif (allocated(OBC%tres_x)) then + elseif (associated(OBC%tres_x)) then do m=1,OBC%ntr call pass_var(OBC%tres_x(:,:,:,m), G%Domain, position=EAST_FACE) enddo - elseif (allocated(OBC%tres_y)) then + elseif (associated(OBC%tres_y)) then do m=1,OBC%ntr call pass_var(OBC%tres_y(:,:,:,m), G%Domain, position=NORTH_FACE) enddo @@ -2009,16 +2009,16 @@ subroutine open_boundary_dealloc(OBC) if (allocated(OBC%segment)) deallocate(OBC%segment) if (allocated(OBC%segnum_u)) deallocate(OBC%segnum_u) if (allocated(OBC%segnum_v)) deallocate(OBC%segnum_v) - if (allocated(OBC%rx_normal)) deallocate(OBC%rx_normal) - if (allocated(OBC%ry_normal)) deallocate(OBC%ry_normal) - if (allocated(OBC%rx_oblique_u)) deallocate(OBC%rx_oblique_u) - if (allocated(OBC%ry_oblique_u)) deallocate(OBC%ry_oblique_u) - if (allocated(OBC%rx_oblique_v)) deallocate(OBC%rx_oblique_v) - if (allocated(OBC%ry_oblique_v)) deallocate(OBC%ry_oblique_v) - if (allocated(OBC%cff_normal_u)) deallocate(OBC%cff_normal_u) - if (allocated(OBC%cff_normal_v)) deallocate(OBC%cff_normal_v) - if (allocated(OBC%tres_x)) deallocate(OBC%tres_x) - if (allocated(OBC%tres_y)) deallocate(OBC%tres_y) + if (associated(OBC%rx_normal)) nullify(OBC%rx_normal) + if (associated(OBC%ry_normal)) nullify(OBC%ry_normal) + if (associated(OBC%rx_oblique_u)) nullify(OBC%rx_oblique_u) + if (associated(OBC%ry_oblique_u)) nullify(OBC%ry_oblique_u) + if (associated(OBC%rx_oblique_v)) nullify(OBC%rx_oblique_v) + if (associated(OBC%ry_oblique_v)) nullify(OBC%ry_oblique_v) + if (associated(OBC%cff_normal_u)) nullify(OBC%cff_normal_u) + if (associated(OBC%cff_normal_v)) nullify(OBC%cff_normal_v) + if (associated(OBC%tres_x)) nullify(OBC%tres_x) + if (associated(OBC%tres_y)) nullify(OBC%tres_y) if (associated(OBC%remap_z_CS)) deallocate(OBC%remap_z_CS) if (associated(OBC%remap_h_CS)) deallocate(OBC%remap_h_CS) deallocate(OBC) @@ -3377,7 +3377,7 @@ subroutine radiation_open_bdry_conds(OBC, u_new, u_old, v_new, v_old, G, GV, US, haloshift=0, symmetric=sym, unscale=1.0/US%L_T_to_m_s**2) endif if (OBC%ntr == 0) return - if (.not. allocated (OBC%tres_x) .or. .not. allocated (OBC%tres_y)) return + if (.not. associated (OBC%tres_x) .or. .not. associated (OBC%tres_y)) return do m=1,OBC%ntr write(var_num,'(I3.3)') m call uvchksum("radiation_OBCs: OBC%tres_[xy]_"//var_num, OBC%tres_x(:,:,:,m), OBC%tres_y(:,:,:,m), G%HI, & @@ -5497,7 +5497,7 @@ subroutine update_segment_tracer_reservoirs(G, GV, uhr, vhr, h, OBC, dt, Reg) ((1.0-a_out+a_in)*segment%tr_Reg%Tr(m)%tres(I,j,k)+ & ((u_L_out+a_out)*Reg%Tr(ntr_id)%t(I+ishift,j,k) - & (u_L_in+a_in)*segment%tr_Reg%Tr(m)%t(I,j,k))) - if (allocated(OBC%tres_x)) OBC%tres_x(I,j,k,m) = I_scale * segment%tr_Reg%Tr(m)%tres(I,j,k) + if (associated(OBC%tres_x)) OBC%tres_x(I,j,k,m) = I_scale * segment%tr_Reg%Tr(m)%tres(I,j,k) enddo ; endif enddo enddo @@ -5537,7 +5537,7 @@ subroutine update_segment_tracer_reservoirs(G, GV, uhr, vhr, h, OBC, dt, Reg) ((1.0-a_out+a_in)*segment%tr_Reg%Tr(m)%tres(i,J,k) + & ((v_L_out+a_out)*Reg%Tr(ntr_id)%t(i,J+jshift,k) - & (v_L_in+a_in)*segment%tr_Reg%Tr(m)%t(i,J,k))) - if (allocated(OBC%tres_y)) OBC%tres_y(i,J,k,m) = I_scale * segment%tr_Reg%Tr(m)%tres(i,J,k) + if (associated(OBC%tres_y)) OBC%tres_y(i,J,k,m) = I_scale * segment%tr_Reg%Tr(m)%tres(i,J,k) enddo ; endif enddo enddo @@ -5613,7 +5613,7 @@ subroutine remap_OBC_fields(G, GV, h_old, h_new, OBC, PCM_cell) ! Update tracer concentrations segment%tr_Reg%Tr(m)%tres(I,j,:) = tr_column(:) - if (allocated(OBC%tres_x)) then ; do k=1,nz + if (associated(OBC%tres_x)) then ; do k=1,nz OBC%tres_x(I,j,k,m) = I_scale * segment%tr_Reg%Tr(m)%tres(I,j,k) enddo ; endif @@ -5680,7 +5680,7 @@ subroutine remap_OBC_fields(G, GV, h_old, h_new, OBC, PCM_cell) ! Update tracer concentrations segment%tr_Reg%Tr(m)%tres(i,J,:) = tr_column(:) - if (allocated(OBC%tres_y)) then ; do k=1,nz + if (associated(OBC%tres_y)) then ; do k=1,nz OBC%tres_y(i,J,k,m) = I_scale * segment%tr_Reg%Tr(m)%tres(i,J,k) enddo ; endif From 0980cb069f29437fdcc775743c67f2fa5a629682 Mon Sep 17 00:00:00 2001 From: Kate Hedstrom Date: Fri, 22 Nov 2024 10:48:08 -0900 Subject: [PATCH 06/11] Another OBC fix, this for the barotropic mode. --- src/core/MOM_open_boundary.F90 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/MOM_open_boundary.F90 b/src/core/MOM_open_boundary.F90 index 83ff646a24..66957fd38e 100644 --- a/src/core/MOM_open_boundary.F90 +++ b/src/core/MOM_open_boundary.F90 @@ -6125,6 +6125,14 @@ subroutine rotate_OBC_segment_data(segment_in, segment, turns) segment%field(n)%buffer_src) endif + if (allocated(segment_in%field(n)%buffer_dst)) then + call allocate_rotated_array(segment_in%field(n)%buffer_dst, & + lbound(segment_in%field(n)%buffer_dst), turns, & + segment%field(n)%buffer_dst) + call rotate_array(segment_in%field(n)%buffer_dst, turns, & + segment%field(n)%buffer_dst) + endif + segment%field(n)%nk_src = segment_in%field(n)%nk_src if (allocated(segment_in%field(n)%dz_src)) then @@ -6138,6 +6146,8 @@ subroutine rotate_OBC_segment_data(segment_in, segment, turns) segment%field(n)%value = segment_in%field(n)%value enddo + call rotate_array(segment_in%SSH, turns, segment%SSH) + segment%temp_segment_data_exists = segment_in%temp_segment_data_exists segment%salt_segment_data_exists = segment_in%salt_segment_data_exists end subroutine rotate_OBC_segment_data From 26820156ca88fddf6f677d9e29bf9a23b6dcc64c Mon Sep 17 00:00:00 2001 From: Kate Hedstrom Date: Sat, 23 Nov 2024 08:06:25 -0900 Subject: [PATCH 07/11] More OBC rotation foxes. Still not out of the woods. --- src/core/MOM_open_boundary.F90 | 43 +++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/core/MOM_open_boundary.F90 b/src/core/MOM_open_boundary.F90 index 66957fd38e..a5b71d95c5 100644 --- a/src/core/MOM_open_boundary.F90 +++ b/src/core/MOM_open_boundary.F90 @@ -6146,7 +6146,48 @@ subroutine rotate_OBC_segment_data(segment_in, segment, turns) segment%field(n)%value = segment_in%field(n)%value enddo - call rotate_array(segment_in%SSH, turns, segment%SSH) + if (allocated(segment_in%SSH)) & + call rotate_array(segment_in%SSH, turns, segment%SSH) + if (allocated(segment_in%cg)) & + call rotate_array(segment_in%cg, turns, segment%cg) + if (allocated(segment_in%htot)) & + call rotate_array(segment_in%htot, turns, segment%htot) + if (allocated(segment_in%dztot)) & + call rotate_array(segment_in%dztot, turns, segment%dztot) + if (allocated(segment_in%h)) & + call rotate_array(segment_in%h, turns, segment%h) + if (allocated(segment_in%normal_vel)) & + call rotate_array(segment_in%normal_vel, turns, segment%normal_vel) + if (allocated(segment_in%normal_trans)) & + call rotate_array(segment_in%normal_trans, turns, segment%normal_trans) + if (allocated(segment_in%normal_vel_bt)) & + call rotate_array(segment_in%normal_vel_bt, turns, segment%normal_vel_bt) + if (allocated(segment_in%tangential_vel)) & + call rotate_array(segment_in%tangential_vel, turns, segment%tangential_vel) + if (allocated(segment_in%tangential_grad)) & + call rotate_array(segment_in%tangential_grad, turns, segment%tangential_grad) + if (allocated(segment_in%grad_normal)) & + call rotate_array(segment_in%grad_normal, turns, segment%grad_normal) + if (allocated(segment_in%grad_tan)) & + call rotate_array(segment_in%grad_tan, turns, segment%grad_tan) + if (allocated(segment_in%grad_gradient)) & + call rotate_array(segment_in%grad_gradient, turns, segment%grad_gradient) + if (allocated(segment_in%rx_norm_rad)) & + call rotate_array(segment_in%rx_norm_rad, turns, segment%ry_norm_rad) + if (allocated(segment_in%ry_norm_rad)) & + call rotate_array(segment_in%ry_norm_rad, turns, segment%rx_norm_rad) + if (allocated(segment_in%rx_norm_obl)) & + call rotate_array(segment_in%rx_norm_obl, turns, segment%ry_norm_obl) + if (allocated(segment_in%ry_norm_obl)) & + call rotate_array(segment_in%ry_norm_obl, turns, segment%rx_norm_obl) + if (allocated(segment_in%cff_normal)) & + call rotate_array(segment_in%cff_normal, turns, segment%cff_normal) + if (allocated(segment_in%nudged_normal_vel)) & + call rotate_array(segment_in%nudged_normal_vel, turns, segment%nudged_normal_vel) + if (allocated(segment_in%nudged_tangential_vel)) & + call rotate_array(segment_in%nudged_tangential_vel, turns, segment%nudged_tangential_vel) + if (allocated(segment_in%nudged_tangential_grad)) & + call rotate_array(segment_in%nudged_tangential_grad, turns, segment%nudged_tangential_grad) segment%temp_segment_data_exists = segment_in%temp_segment_data_exists segment%salt_segment_data_exists = segment_in%salt_segment_data_exists From cc26659d6d2c1a32007b25bb08e7e682f6362ac0 Mon Sep 17 00:00:00 2001 From: Kate Hedstrom Date: Wed, 27 Nov 2024 17:26:44 -0900 Subject: [PATCH 08/11] Fixing case on tr_Reg. Still not rototing OBCs correctly. --- src/core/MOM.F90 | 9 +++++++-- src/core/MOM_open_boundary.F90 | 9 +++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index 3ab558361f..95d58f31cb 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -113,7 +113,7 @@ module MOM use MOM_open_boundary, only : ocean_OBC_type, OBC_registry_type use MOM_open_boundary, only : register_temp_salt_segments, update_segment_tracer_reservoirs use MOM_open_boundary, only : open_boundary_register_restarts, remap_OBC_fields -use MOM_open_boundary, only : open_boundary_setup_vert +use MOM_open_boundary, only : open_boundary_setup_vert, update_OBC_segment_data use MOM_open_boundary, only : rotate_OBC_config, rotate_OBC_init use MOM_porous_barriers, only : porous_widths_layer, porous_widths_interface, porous_barriers_init use MOM_porous_barriers, only : porous_barrier_CS @@ -3039,8 +3039,13 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, & call update_ALE_sponge_field(CS%ALE_sponge_CSp, S_in, G, GV, CS%S) endif - if (associated(OBC_in)) & + if (associated(OBC_in)) then call rotate_OBC_init(OBC_in, G, GV, US, param_file, CS%tv, restart_CSp, CS%OBC) + if (CS%OBC%some_need_no_IO_for_data) then + call calc_derived_thermo(CS%tv, CS%h, G, GV, US) + call update_OBC_segment_data(G, GV, US, CS%OBC, CS%tv, CS%h, Time) + endif + endif deallocate(u_in) deallocate(v_in) diff --git a/src/core/MOM_open_boundary.F90 b/src/core/MOM_open_boundary.F90 index a5b71d95c5..379fb5a34a 100644 --- a/src/core/MOM_open_boundary.F90 +++ b/src/core/MOM_open_boundary.F90 @@ -5471,8 +5471,8 @@ subroutine update_segment_tracer_reservoirs(G, GV, uhr, vhr, h, OBC, dt, Reg) if (G%mask2dT(I+ishift,j) == 0.0) cycle ! Update the reservoir tracer concentration implicitly using a Backward-Euler timestep do m=1,segment%tr_Reg%ntseg - ntr_id = segment%tr_reg%Tr(m)%ntr_index - fd_id = segment%tr_reg%Tr(m)%fd_index + ntr_id = segment%tr_Reg%Tr(m)%ntr_index + fd_id = segment%tr_Reg%Tr(m)%fd_index if (fd_id == -1) then resrv_lfac_out = 1.0 resrv_lfac_in = 1.0 @@ -5515,8 +5515,8 @@ subroutine update_segment_tracer_reservoirs(G, GV, uhr, vhr, h, OBC, dt, Reg) if (G%mask2dT(i,j+jshift) == 0.0) cycle ! Update the reservoir tracer concentration implicitly using a Backward-Euler timestep do m=1,segment%tr_Reg%ntseg - ntr_id = segment%tr_reg%Tr(m)%ntr_index - fd_id = segment%tr_reg%Tr(m)%fd_index + ntr_id = segment%tr_Reg%Tr(m)%ntr_index + fd_id = segment%tr_Reg%Tr(m)%fd_index if (fd_id == -1) then resrv_lfac_out = 1.0 resrv_lfac_in = 1.0 @@ -6102,6 +6102,7 @@ subroutine rotate_OBC_segment_data(segment_in, segment, turns) segment%field(n)%name = 'Vphase' case ('V') segment%field(n)%name = 'U' + segment%field(n)%value = -segment%field(n)%value case ('Vamp') segment%field(n)%name = 'Uamp' case ('Vphase') From dfe0f22fd176cea16d565782cec8aa08514d3f0b Mon Sep 17 00:00:00 2001 From: Kate Hedstrom Date: Thu, 28 Nov 2024 11:16:36 -0900 Subject: [PATCH 09/11] Looks good for the first few steps, then not so much. --- src/core/MOM_open_boundary.F90 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/core/MOM_open_boundary.F90 b/src/core/MOM_open_boundary.F90 index 379fb5a34a..dd84558bab 100644 --- a/src/core/MOM_open_boundary.F90 +++ b/src/core/MOM_open_boundary.F90 @@ -6092,6 +6092,14 @@ subroutine rotate_OBC_segment_data(segment_in, segment, turns) segment%field(n)%handle = segment_in%field(n)%handle segment%field(n)%dz_handle = segment_in%field(n)%dz_handle + if (allocated(segment_in%field(n)%buffer_dst)) then + call allocate_rotated_array(segment_in%field(n)%buffer_dst, & + lbound(segment_in%field(n)%buffer_dst), turns, & + segment%field(n)%buffer_dst) + call rotate_array(segment_in%field(n)%buffer_dst, turns, & + segment%field(n)%buffer_dst) + endif + if (modulo(turns, 2) /= 0) then select case (segment_in%field(n)%name) case ('U') @@ -6102,7 +6110,7 @@ subroutine rotate_OBC_segment_data(segment_in, segment, turns) segment%field(n)%name = 'Vphase' case ('V') segment%field(n)%name = 'U' - segment%field(n)%value = -segment%field(n)%value + segment%field(n)%buffer_dst(:,:,:) = -segment%field(n)%buffer_dst(:,:,:) case ('Vamp') segment%field(n)%name = 'Uamp' case ('Vphase') @@ -6126,14 +6134,6 @@ subroutine rotate_OBC_segment_data(segment_in, segment, turns) segment%field(n)%buffer_src) endif - if (allocated(segment_in%field(n)%buffer_dst)) then - call allocate_rotated_array(segment_in%field(n)%buffer_dst, & - lbound(segment_in%field(n)%buffer_dst), turns, & - segment%field(n)%buffer_dst) - call rotate_array(segment_in%field(n)%buffer_dst, turns, & - segment%field(n)%buffer_dst) - endif - segment%field(n)%nk_src = segment_in%field(n)%nk_src if (allocated(segment_in%field(n)%dz_src)) then From 56dc95eae383e90455c56a8c73cd2d451f41e70a Mon Sep 17 00:00:00 2001 From: Kate Hedstrom Date: Wed, 4 Dec 2024 12:37:57 -0900 Subject: [PATCH 10/11] Making barotropic fix look symmetric. --- src/core/MOM.F90 | 8 ++------ src/core/MOM_barotropic.F90 | 31 ++++++++++++++++++++++++------- src/core/MOM_open_boundary.F90 | 6 +++--- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index 95d58f31cb..9f6745583e 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -114,6 +114,7 @@ module MOM use MOM_open_boundary, only : register_temp_salt_segments, update_segment_tracer_reservoirs use MOM_open_boundary, only : open_boundary_register_restarts, remap_OBC_fields use MOM_open_boundary, only : open_boundary_setup_vert, update_OBC_segment_data +use MOM_open_boundary, only : initialize_segment_data use MOM_open_boundary, only : rotate_OBC_config, rotate_OBC_init use MOM_porous_barriers, only : porous_widths_layer, porous_widths_interface, porous_barriers_init use MOM_porous_barriers, only : porous_barrier_CS @@ -3039,13 +3040,8 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, & call update_ALE_sponge_field(CS%ALE_sponge_CSp, S_in, G, GV, CS%S) endif - if (associated(OBC_in)) then + if (associated(OBC_in)) & call rotate_OBC_init(OBC_in, G, GV, US, param_file, CS%tv, restart_CSp, CS%OBC) - if (CS%OBC%some_need_no_IO_for_data) then - call calc_derived_thermo(CS%tv, CS%h, G, GV, US) - call update_OBC_segment_data(G, GV, US, CS%OBC, CS%tv, CS%h, Time) - endif - endif deallocate(u_in) deallocate(v_in) diff --git a/src/core/MOM_barotropic.F90 b/src/core/MOM_barotropic.F90 index fa2cadfa7f..ba31f2b378 100644 --- a/src/core/MOM_barotropic.F90 +++ b/src/core/MOM_barotropic.F90 @@ -2457,16 +2457,33 @@ subroutine btstep(U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, forces, pbce, ! Update factor so that nothing changes outside of the OBC (problem for interior OBCs only) if (associated(OBC)) then ; if (OBC%OBC_pe) then - do j=jsv,jev +! do j=jsv,jev +! if (OBC%specified_u_BCs_exist_globally .or. OBC%open_u_BCs_exist_globally) then +! do i=isv,iev-1 ; if (OBC%segnum_u(I,j) /= OBC_NONE) then +! if (OBC%segment(OBC%segnum_u(I,j))%direction == OBC_DIRECTION_E) then +! factor(i+1,j) = 0.0 +! elseif (OBC%segment(OBC%segnum_u(I,j))%direction == OBC_DIRECTION_W) then +! factor(i,j) = 0.0 +! endif +! endif ; enddo +! endif + do i=isv,iev if (OBC%specified_u_BCs_exist_globally .or. OBC%open_u_BCs_exist_globally) then - do i=isv,iev-1 ; if (OBC%segnum_u(I,j) /= OBC_NONE) then - if (OBC%segment(OBC%segnum_u(I,j))%direction == OBC_DIRECTION_E) then - factor(i+1,j) = 0.0 - elseif (OBC%segment(OBC%segnum_u(I,j))%direction == OBC_DIRECTION_W) then - factor(i,j) = 0.0 + do j=jsv,jev + if (OBC%segnum_u(I-1,j) /= OBC_NONE) then + if (OBC%segment(OBC%segnum_u(I-1,j))%direction == OBC_DIRECTION_E) then + factor(i,j) = 0.0 + endif + endif + if (OBC%segnum_u(I,j) /= OBC_NONE) then + if (OBC%segment(OBC%segnum_u(I,j))%direction == OBC_DIRECTION_W) then + factor(i,j) = 0.0 + endif endif - endif ; enddo + enddo endif + enddo + do j=jsv,jev if (OBC%specified_v_BCs_exist_globally .or. OBC%open_v_BCs_exist_globally) then do i=isv,iev if (OBC%segnum_v(i,J-1) /= OBC_NONE) then diff --git a/src/core/MOM_open_boundary.F90 b/src/core/MOM_open_boundary.F90 index dd84558bab..ad9ad04280 100644 --- a/src/core/MOM_open_boundary.F90 +++ b/src/core/MOM_open_boundary.F90 @@ -6063,13 +6063,13 @@ subroutine rotate_OBC_init(OBC_in, G, GV, US, param_file, tv, restart_CS, OBC) "If true, Temperature and salinity are used as state "//& "variables.", default=.true., do_not_log=.true.) + if (use_temperature) & + call fill_temp_salt_segments(G, GV, US, OBC, tv) + do l = 1, OBC%number_of_segments call rotate_OBC_segment_data(OBC_in%segment(l), OBC%segment(l), G%HI%turns) enddo - if (use_temperature) & - call fill_temp_salt_segments(G, GV, US, OBC, tv) - call open_boundary_init(G, GV, US, param_file, OBC, restart_CS) end subroutine rotate_OBC_init From ec17094794ffbdc8de0e2036f6e1dcf76e39d83f Mon Sep 17 00:00:00 2001 From: Kate Hedstrom Date: Wed, 4 Dec 2024 12:37:57 -0900 Subject: [PATCH 11/11] Making barotropic fix look symmetric. --- src/core/MOM.F90 | 3 +-- src/core/MOM_open_boundary.F90 | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index 9f6745583e..3ab558361f 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -113,8 +113,7 @@ module MOM use MOM_open_boundary, only : ocean_OBC_type, OBC_registry_type use MOM_open_boundary, only : register_temp_salt_segments, update_segment_tracer_reservoirs use MOM_open_boundary, only : open_boundary_register_restarts, remap_OBC_fields -use MOM_open_boundary, only : open_boundary_setup_vert, update_OBC_segment_data -use MOM_open_boundary, only : initialize_segment_data +use MOM_open_boundary, only : open_boundary_setup_vert use MOM_open_boundary, only : rotate_OBC_config, rotate_OBC_init use MOM_porous_barriers, only : porous_widths_layer, porous_widths_interface, porous_barriers_init use MOM_porous_barriers, only : porous_barrier_CS diff --git a/src/core/MOM_open_boundary.F90 b/src/core/MOM_open_boundary.F90 index ad9ad04280..c485a37da6 100644 --- a/src/core/MOM_open_boundary.F90 +++ b/src/core/MOM_open_boundary.F90 @@ -6189,6 +6189,50 @@ subroutine rotate_OBC_segment_data(segment_in, segment, turns) call rotate_array(segment_in%nudged_tangential_vel, turns, segment%nudged_tangential_vel) if (allocated(segment_in%nudged_tangential_grad)) & call rotate_array(segment_in%nudged_tangential_grad, turns, segment%nudged_tangential_grad) + if (associated(segment_in%tr_Reg)) then + do n = 1, segment_in%tr_Reg%ntseg + call rotate_array(segment_in%tr_Reg%tr(n)%tres, turns, segment%tr_Reg%tr(n)%tres) + ! Testing this to see if it works for contant tres values. Probably wrong otherwise. + segment%tr_Reg%Tr(n)%is_initialized=.true. + enddo + endif + + ! Only doing this here for 1 turns, get flow directed in the opposite direction. + ! Currents that are now E_W were N_S and the turns should change their sign. + if (turns == 1 .and. segment%is_E_or_W) then + if (allocated(segment_in%normal_vel)) & + segment%normal_vel(:,:,:) = - segment%normal_vel(:,:,:) + if (allocated(segment_in%normal_trans)) & + segment%normal_trans(:,:,:) = - segment%normal_trans(:,:,:) + if (allocated(segment_in%normal_vel_bt)) & + segment%normal_vel_bt(:,:) = - segment%normal_vel_bt(:,:) + if (allocated(segment_in%tangential_vel)) & + segment%tangential_vel(:,:,:) = - segment%tangential_vel(:,:,:) + if (allocated(segment_in%tangential_grad)) & + segment%tangential_grad(:,:,:) = - segment%tangential_grad(:,:,:) + if (allocated(segment_in%grad_normal)) & + segment%grad_normal(:,:,:) = - segment%grad_normal(:,:,:) + if (allocated(segment_in%grad_tan)) & + segment%grad_tan(:,:,:) = - segment%grad_tan(:,:,:) + if (allocated(segment_in%grad_gradient)) & + segment%grad_gradient(:,:,:) = - segment%grad_gradient(:,:,:) + if (allocated(segment%rx_norm_rad)) & + segment%rx_norm_rad(:,:,:) = - segment%rx_norm_rad(:,:,:) + if (allocated(segment%ry_norm_rad)) & + segment%ry_norm_rad(:,:,:) = - segment%ry_norm_rad(:,:,:) + if (allocated(segment%rx_norm_obl)) & + segment%rx_norm_obl(:,:,:) = - segment%rx_norm_obl(:,:,:) + if (allocated(segment%ry_norm_obl)) & + segment%ry_norm_obl(:,:,:) = - segment%ry_norm_obl(:,:,:) + if (allocated(segment_in%cff_normal)) & + segment%cff_normal(:,:,:) = - segment%cff_normal(:,:,:) + if (allocated(segment_in%nudged_normal_vel)) & + segment%nudged_normal_vel(:,:,:) = - segment%nudged_normal_vel(:,:,:) + if (allocated(segment_in%nudged_tangential_vel)) & + segment%nudged_tangential_vel(:,:,:) = - segment%nudged_tangential_vel(:,:,:) + if (allocated(segment_in%nudged_tangential_grad)) & + segment%nudged_tangential_grad(:,:,:) = - segment%nudged_tangential_grad(:,:,:) + endif segment%temp_segment_data_exists = segment_in%temp_segment_data_exists segment%salt_segment_data_exists = segment_in%salt_segment_data_exists