MOM6
MOM_legacy_barotropic.F90
Go to the documentation of this file.
2 !***********************************************************************
3 !* GNU General Public License *
4 !* This file is a part of MOM. *
5 !* *
6 !* MOM is free software; you can redistribute it and/or modify it and *
7 !* are expected to follow the terms of the GNU General Public License *
8 !* as published by the Free Software Foundation; either version 2 of *
9 !* the License, or (at your option) any later version. *
10 !* *
11 !* MOM is distributed in the hope that it will be useful, but WITHOUT *
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
13 !* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public *
14 !* License for more details. *
15 !* *
16 !* For the full text of the GNU General Public License, *
17 !* write to: Free Software Foundation, Inc., *
18 !* 675 Mass Ave, Cambridge, MA 02139, USA. *
19 !* or see: http://www.gnu.org/licenses/gpl.html *
20 !***********************************************************************
21 
22 !********+*********+*********+*********+*********+*********+*********+**
23 !* *
24 !* By Robert Hallberg, April 1994 - January 2007 *
25 !* *
26 !* This program contains the subroutines that time steps the *
27 !* linearized barotropic equations. btstep is used to actually *
28 !* time step the barotropic equations, and contains most of the *
29 !* substance of this module. *
30 !* *
31 !* btstep uses a forwards-backwards based scheme to time step *
32 !* the barotropic equations, returning the layers' accelerations due *
33 !* to the barotropic changes in the ocean state, the final free *
34 !* surface height (or column mass), and the volume (or mass) fluxes *
35 !* summed through the layers and averaged over the baroclinic time *
36 !* step. As input, btstep takes the initial 3-D velocities, the *
37 !* inital free surface height, the 3-D accelerations of the layers, *
38 !* and the external forcing. Everything in btstep is cast in terms *
39 !* of anomalies, so if everything is in balance, there is explicitly *
40 !* no acceleration due to btstep. *
41 !* *
42 !* The spatial discretization of the continuity equation is second *
43 !* order accurate. A flux conservative form is used to guarantee *
44 !* global conservation of volume. The spatial discretization of the *
45 !* momentum equation is second order accurate. The Coriolis force *
46 !* is written in a form which does not contribute to the energy *
47 !* tendency and which conserves linearized potential vorticity, f/D. *
48 !* These terms are exactly removed from the baroclinic momentum *
49 !* equations, so the linearization of vorticity advection will not *
50 !* degrade the overall solution. *
51 !* *
52 !* btcalc calculates the fractional thickness of each layer at the *
53 !* velocity points, for later use in calculating the barotropic *
54 !* velocities and the averaged accelerations. Harmonic mean *
55 !* thicknesses (i.e. 2*h_L*h_R/(h_L + h_R)) are used to avoid overly *
56 !* strong weighting of overly thin layers. This may later be relaxed *
57 !* to use thicknesses determined from the continuity equations. *
58 !* *
59 !* bt_mass_source determines the real mass sources for the *
60 !* barotropic solver, along with the corrective pseudo-fluxes that *
61 !* keep the barotropic and baroclinic estimates of the free surface *
62 !* height close to each other. Given the layer thicknesses and the *
63 !* free surface height that correspond to each other, it calculates *
64 !* a corrective mass source that is added to the barotropic continuity*
65 !* equation, and optionally adjusts a slowly varying correction rate. *
66 !* Newer algorithmic changes have deemphasized the need for this, but *
67 !* it is still here to add net water sources to the barotropic solver.*
68 !* *
69 !* barotropic_init allocates and initializes any barotropic arrays *
70 !* that have not been read from a restart file, reads parameters from *
71 !* the inputfile, and sets up diagnostic fields. *
72 !* *
73 !* barotropic_end deallocates anything allocated in barotropic_init *
74 !* or register_barotropic_restarts. *
75 !* *
76 !* register_barotropic_restarts is used to indicate any fields that *
77 !* are private to the barotropic solver that need to be included in *
78 !* the restart files, and to ensure that they are read. *
79 !* *
80 !* A small fragment of the grid is shown below: *
81 !* *
82 !* j+1 x ^ x ^ x At x: q, CoriolisBu *
83 !* j+1 > o > o > At ^: v_in, vbt, accel_layer_v, vbtav *
84 !* j x ^ x ^ x At >: u_in, ubt, accel_layer_u, ubtav, amer *
85 !* j > o > o > At o: eta, h, bathyT, pbce *
86 !* j-1 x ^ x ^ x *
87 !* i-1 i i+1 *
88 !* i i+1 *
89 !* *
90 !* The boundaries always run through q grid points (x). *
91 !* *
92 !********+*********+*********+*********+*********+*********+*********+**
93 
94 use mom_debugging, only : hchksum, uvchksum
95 use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, clock_routine
97 use mom_diag_mediator, only : safe_alloc_ptr, diag_ctrl, enable_averaging
98 use mom_domains, only : pass_var, pass_vector, min_across_pes, clone_mom_domain
101 use mom_domains, only : to_all, scalar_pair, agrid, corner, mom_domain_type
104 use mom_error_handler, only : mom_error, mom_mesg, fatal, warning, is_root_pe
106 use mom_forcing_type, only : forcing
107 use mom_grid, only : ocean_grid_type
108 use mom_hor_index, only : hor_index_type
109 use mom_io, only : vardesc, var_desc
115 use mom_time_manager, only : time_type, set_time, operator(+), operator(-)
118 
119 implicit none ; private
120 
121 #include <MOM_memory.h>
122 #ifdef STATIC_MEMORY_
123 # ifndef BTHALO_
124 # define BTHALO_ 0
125 # endif
126 # define WHALOI_ MAX(BTHALO_-NIHALO_,0)
127 # define WHALOJ_ MAX(BTHALO_-NJHALO_,0)
128 # define NIMEMW_ 1-WHALOI_:NIMEM_+WHALOI_
129 # define NJMEMW_ 1-WHALOJ_:NJMEM_+WHALOJ_
130 # define NIMEMBW_ -WHALOI_:NIMEM_+WHALOI_
131 # define NJMEMBW_ -WHALOJ_:NJMEM_+WHALOJ_
132 # define SZIW_(G) NIMEMW_
133 # define SZJW_(G) NJMEMW_
134 # define SZIBW_(G) NIMEMBW_
135 # define SZJBW_(G) NJMEMBW_
136 #else
137 # define NIMEMW_ :
138 # define NJMEMW_ :
139 # define NIMEMBW_ :
140 # define NJMEMBW_ :
141 # define SZIW_(G) G%isdw:G%iedw
142 # define SZJW_(G) G%jsdw:G%jedw
143 # define SZIBW_(G) G%isdw-1:G%iedw
144 # define SZJBW_(G) G%jsdw-1:G%jedw
145 #endif
146 
149 
150 type, public :: legacy_barotropic_cs ; private
151  real allocable_, dimension(NIMEMB_PTR_,NJMEM_,NKMEM_) :: frhatu
152  real allocable_, dimension(NIMEM_,NJMEMB_PTR_,NKMEM_) :: frhatv
153  ! frhatu and frhatv are the fraction of the total column thickness
154  ! interpolated to u or v grid points in each layer, nondimensional.
155  real allocable_, dimension(NIMEMB_PTR_,NJMEM_) :: &
156  idatu, & ! Inverse of the basin depth at u grid points, in m-1.
157  uhbt_ic, & ! The barotropic solver's estimate of the zonal
158  ! transport as the initla condition for the next call
159  ! to btstep, in H m2 s-1.
160  ubt_ic, & ! The barotropic solver's estimate of the zonal velocity
161  ! that will be the initial condition for the next call
162  ! to btstep, in m s-1.
163  ubtav ! The barotropic zonal velocity averaged over the
164  ! baroclinic time step, m s-1.
165  real allocable_, dimension(NIMEM_,NJMEMB_PTR_) :: &
166  idatv, & ! Inverse of the basin depth at v grid points, in m-1.
167  vhbt_ic, & ! The barotropic solver's estimate of the zonal
168  ! transport as the initla condition for the next call
169  ! to btstep, in H m2 s-1.
170  vbt_ic, & ! The barotropic solver's estimate of the zonal velocity
171  ! that will be the initial condition for the next call
172  ! to btstep, in m s-1.
173  vbtav ! The barotropic meridional velocity averaged over the
174  ! baroclinic time step, m s-1.
175  real allocable_, dimension(NIMEM_,NJMEM_) :: &
176  eta_source, & ! The net mass source to be applied within the
177  ! barotropic solver, in H s-1.
178  eta_cor, & ! The difference between the free surface height from
179  ! the barotropic calculation and the sum of the layer
180  ! thicknesses. This difference is imposed as a forcing
181  ! term in the barotropic calculation over a baroclinic
182  ! timestep, in H (m or kg m-2).
183  eta_cor_bound ! A limit on the rate at which eta_cor can be applied
184  ! while avoiding instability, in units of H s-1. This
185  ! is only used if CS%bound_BT_corr is true.
186  real allocable_, dimension(NIMEMW_,NJMEMW_) :: &
187  ua_polarity, & ! Test vector components for checking grid polarity.
188  va_polarity, & ! Test vector components for checking grid polarity.
189  bathyt ! A copy of bathyT (ocean bottom depth) with wide halos.
190  real allocable_, dimension(NIMEMW_,NJMEMW_) :: &
191  iareat ! This is a copy of G%IareaT with wide halos, but will
192  ! still utilize the macro IareaT when referenced, m-2.
193  real allocable_, dimension(NIMEMBW_,NJMEMW_) :: &
194  datu_res, & ! A nondimensional factor by which the zonal face areas
195  ! are to be rescaled to account for the effective face
196  ! areas of the layers, if rescale_D_bt is true.
197  ! Datu_res is set in btcalc.
198  d_u_cor, & ! A simply averaged depth at u points, in m.
199  dy_cu, & ! A copy of G%dy_Cu with wide halos, in m.
200  idxcu ! A copy of G%IdxCu with wide halos, in m-1.
201  real allocable_, dimension(NIMEMW_,NJMEMBW_) :: &
202  datv_res, & ! A nondimensional factor by which the meridional face
203  ! areas are to be rescaled to account for the effective
204  ! face areas of the layers, if rescale_D_bt is true.
205  ! Datv_res is set in btcalc.
206  d_v_cor, & ! A simply averaged depth at v points, in m.
207  dx_cv, & ! A copy of G%dx_Cv with wide halos, in m.
208  idycv ! A copy of G%IdyCv with wide halos, in m-1.
209  real allocable_, dimension(NIMEMBW_,NJMEMBW_) :: &
210  q_d ! f / D at PV points, in m-1 s-1.
211 
212  real, pointer, dimension(:,:,:) :: frhatu1, frhatv1 ! Predictor values.
213 
214  real :: rho0 ! The density used in the Boussinesq
215  ! approximation, in kg m-3.
216  real :: dtbt ! The barotropic time step, in s.
217  real :: dtbt_fraction ! The fraction of the maximum time-step that
218  ! should used. The default is 0.98.
219  real :: dtbt_max ! The maximum stable barotropic time step, in s.
220  real :: dt_bt_filter ! The time-scale over which the barotropic mode
221  ! solutions are filtered, in s. This can never
222  ! be taken to be longer than 2*dt. The default, 0,
223  ! applies no filtering.
224  integer :: nstep_last = 0 ! The number of barotropic timesteps per baroclinic
225  ! time step the last time btstep was called.
226  real :: bebt ! A nondimensional number, from 0 to 1, that
227  ! determines the gravity wave time stepping scheme.
228  ! 0.0 gives a forward-backward scheme, while 1.0
229  ! give backward Euler. In practice, bebt should be
230  ! of order 0.2 or greater.
231  logical :: split ! If true, use the split time stepping scheme.
232  real :: eta_source_limit ! The fraction of the initial depth of the ocean
233  ! that can be added or removed to the bartropic
234  ! solution within a thermodynamic time step. By
235  ! default this is 0 (i.e., no correction). Nondim.
236  logical :: bound_bt_corr ! If true, the magnitude of the fake mass source
237  ! in the barotropic equation that drives the two
238  ! estimates of the free surface height toward each
239  ! other is bounded to avoid driving corrective
240  ! velocities that exceed 0.1*MAXVEL.
241  logical :: gradual_bt_ics ! If true, adjust the initial conditions for the
242  ! barotropic solver to the values from the layered
243  ! solution over a whole timestep instead of
244  ! instantly. This is a decent approximation to the
245  ! inclusion of sum(u dh_dt) while also correcting
246  ! for truncation errors.
247  logical :: sadourny ! If true, the Coriolis terms are discretized
248  ! with Sadourny's energy conserving scheme,
249  ! otherwise the Arakawa & Hsu scheme is used. If
250  ! the deformation radius is not resolved Sadourny's
251  ! scheme should probably be used.
252  logical :: nonlinear_continuity ! If true, the barotropic continuity equation
253  ! uses the full ocean thickness for transport.
254  integer :: nonlin_cont_update_period ! The number of barotropic time steps
255  ! between updates to the face area, or 0 only to
256  ! update at the start of a call to btstep. The
257  ! default is 1.
258  logical :: bt_project_velocity ! If true, step the barotropic velocity first
259  ! and project out the velocity tendancy by 1+BEBT
260  ! when calculating the transport. The default
261  ! (false) is to use a predictor continuity step to
262  ! find the pressure field, and then do a corrector
263  ! continuity step using a weighted average of the
264  ! old and new velocities, with weights of (1-BEBT)
265  ! and BEBT.
266  logical :: dynamic_psurf ! If true, add a dynamic pressure due to a viscous
267  ! ice shelf, for instance.
268  real :: dmin_dyn_psurf ! The minimum depth to use in limiting the size
269  ! of the dynamic surface pressure for stability,
270  ! in m.
271  real :: ice_strength_length ! The length scale at which the damping rate
272  ! due to the ice strength should be the same as if
273  ! a Laplacian were applied, in m.
274  real :: const_dyn_psurf ! The constant that scales the dynamic surface
275  ! pressure, nondim. Stable values are < ~1.0.
276  ! The default is 0.9.
277  logical :: tides ! If true, apply tidal momentum forcing.
278  real :: g_extra ! A nondimensional factor by which gtot is enhanced.
279  real :: drag_amp ! A nondimensional value (presumably between 0 and
280  ! 1) scaling the magnitude of the bottom drag
281  ! applied in the barotropic solver, 1 by default.
282  integer :: hvel_scheme ! An integer indicating how the thicknesses at
283  ! velocity points are calculated. Valid values are
284  ! given by the parameters defined below:
285  ! HARMONIC, ARITHMETIC, HYBRID, and FROM_BT_CONT
286  logical :: strong_drag ! If true, use a stronger estimate of the retarding
287  ! effects of strong bottom drag.
288  logical :: rescale_d_bt ! If true, the open face areas are rescaled by a
289  ! function of the ratio of the summed harmonic
290  ! mean thicknesses to the harmonic mean of the
291  ! summed thicknesses.
292  logical :: linearized_bt_pv ! If true, the PV and interface thicknesses used
293  ! in the barotropic Coriolis calculation is time
294  ! invariant and linearized.
295  logical :: use_wide_halos ! If true, use wide halos and march in during the
296  ! barotropic time stepping for efficiency.
297  logical :: clip_velocity ! If true, limit any velocity components that
298  ! exceed maxvel. This should only be used as a
299  ! desperate debugging measure.
300  logical :: debug ! If true, write verbose checksums for debugging purposes.
301  logical :: debug_bt ! If true, write verbose checksums for debugging purposes.
302  real :: maxvel ! Velocity components greater than maxvel are
303  ! truncated to maxvel, in m s-1.
304  real :: maxcfl_bt_cont ! The maximum permitted CFL number associated with the
305  ! barotropic accelerations from the summed velocities
306  ! times the time-derivatives of thicknesses. The
307  ! default is 0.1, and there will probably be real
308  ! problems if this were set close to 1.
309  type(time_type), pointer :: time ! A pointer to the ocean model's clock.
310  type(diag_ctrl), pointer :: diag ! A structure that is used to regulate the
311  ! timing of diagnostic output.
312  type(mom_domain_type), pointer :: bt_domain => null()
313  type(hor_index_type), pointer :: debug_bt_hi ! debugging copy of horizontal index_type
314  type(tidal_forcing_cs), pointer :: tides_csp => null()
315  logical :: module_is_initialized = .false.
316 
317  integer :: isdw, iedw, jsdw, jedw ! The memory limits of the wide halo arrays.
318 
319  integer :: id_pfu_bt = -1, id_pfv_bt = -1, id_coru_bt = -1, id_corv_bt = -1
320  integer :: id_ubtforce = -1, id_vbtforce = -1, id_uaccel = -1, id_vaccel = -1
321  integer :: id_visc_rem_u = -1, id_visc_rem_v = -1, id_eta_cor = -1
322  integer :: id_ubt = -1, id_vbt = -1, id_eta_bt = -1, id_ubtav = -1, id_vbtav = -1
323  integer :: id_ubt_st = -1, id_vbt_st = -1, id_eta_st = -1
324  integer :: id_ubt_hifreq = -1, id_vbt_hifreq = -1, id_eta_hifreq = -1
325  integer :: id_uhbt_hifreq = -1, id_vhbt_hifreq = -1, id_eta_pred_hifreq = -1
326  integer :: id_gtotn = -1, id_gtots = -1, id_gtote = -1, id_gtotw = -1
327  integer :: id_datu_res = -1, id_datv_res = -1
328  integer :: id_uhbt = -1, id_frhatu = -1, id_vhbt = -1, id_frhatv = -1
329  integer :: id_frhatu1 = -1, id_frhatv1 = -1
330 end type legacy_barotropic_cs
331 
332 type, private :: local_bt_cont_u_type
333  real :: fa_u_ee, fa_u_e0, fa_u_w0, fa_u_ww
334  real :: ubt_ee, ubt_ww
335  real :: uh_crve, uh_crvw
336  real :: uh_ee, uh_ww
337 end type local_bt_cont_u_type
338 type, private :: local_bt_cont_v_type
339  real :: fa_v_nn, fa_v_n0, fa_v_s0, fa_v_ss
340  real :: vbt_nn, vbt_ss
341  real :: vh_crvn, vh_crvs
342  real :: vh_nn, vh_ss
343 end type local_bt_cont_v_type
344 
345 type, private :: memory_size_type
346  integer :: isdw, iedw, jsdw, jedw ! The memory limits of the wide halo arrays.
347 end type memory_size_type
348 
349 
350 type, private :: bt_obc_type
351  real, dimension(:,:), pointer :: &
352  cg_u => null(), & ! The external wave speed at u-points, in m s-1.
353  cg_v => null(), & ! The external wave speed at u-points, in m s-1.
354  h_u => null(), & ! The total thickness at the u-points, in m or kg m-2.
355  h_v => null(), & ! The total thickness at the v-points, in m or kg m-2.
356  uhbt => null(), & ! The zonal and meridional barotropic thickness fluxes
357  vhbt => null(), & ! specified for open boundary conditions (if any),
358  ! in units of m3 s-1.
359  ubt_outer => null(), & ! The zonal and meridional velocities just outside
360  vbt_outer => null(), & ! the domain, as set by the open boundary conditions,
361  ! in units of m s-1.
362  eta_outer_u => null(), & ! The surface height outside of the domain at a
363  eta_outer_v => null() ! u- or v- point with an open boundary condition,
364  ! in units of m or kg m-2.
365  integer :: is_u_obc, ie_u_obc, js_u_obc, je_u_obc
366  integer :: is_v_obc, ie_v_obc, js_v_obc, je_v_obc
367 end type bt_obc_type
368 
369 integer :: id_clock_sync=-1, id_clock_calc=-1
373 
374 ! Enumeration values for various schemes
375 integer, parameter :: harmonic = 1
376 integer, parameter :: arithmetic = 2
377 integer, parameter :: hybrid = 3
378 integer, parameter :: from_bt_cont = 4
379 integer, parameter :: hybrid_bt_cont = 5
380 character*(20), parameter :: hybrid_string = "HYBRID"
381 character*(20), parameter :: harmonic_string = "HARMONIC"
382 character*(20), parameter :: arithmetic_string = "ARITHMETIC"
383 character*(20), parameter :: bt_cont_string = "FROM_BT_CONT"
384 
385 contains
386 
387 subroutine legacy_btstep(use_fluxes, U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, &
388  fluxes, pbce, eta_PF_in, U_Cor, V_Cor, &
389  accel_layer_u, accel_layer_v, eta_out, uhbtav, vhbtav, G, GV, CS, &
390  visc_rem_u, visc_rem_v, etaav, uhbt_out, vhbt_out, OBC, &
391  BT_cont, eta_PF_start, &
392  taux_bot, tauy_bot, uh0, vh0, u_uh0, v_vh0)
393  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
394  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
395  logical, intent(in) :: use_fluxes !< A logical indicating whether velocities
396  !! (false) or fluxes (true) are used to initialize the barotropic velocities.
397  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
398  intent(in) :: U_in !< The initial (3-D) zonal velocity or
399  !! volume or mass fluxes,depending on flux_form, in m s-1 or m3 s-1 or kg s-1.
400  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
401  intent(in) :: V_in !< The initial (3-D) meridional velocity
402  !! or volume/mass fluxes, depending on flux_form, in m s-1 or m3 s-1 or kg s-1.
403  real, dimension(SZI_(G),SZJ_(G)), &
404  intent(in) :: eta_in !< The initial barotropic free surface
405  !! height anomaly or column mass anomaly, in m or kg m-2.
406  real, &
407  intent(in) :: dt !< The time increment over which to
408  !! integrate, in s.
409  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
410  intent(in) :: bc_accel_u !< The zonal baroclinic accelerations,
411  !! in m s-2.
412  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
413  intent(in) :: bc_accel_v !< The meridional baroclinic
414  !! accelerations, in m s-2.
415  type(forcing), intent(in) :: fluxes !< A structure containing pointers to any
416  !! possible forcing fields. Unused fields have NULL ptrs.
417  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
418  intent(in) :: pbce !< The baroclinic pressure anomaly in each
419  !! layer due to free surface height anomalies, in m2 H-1 s-2.
420  real, dimension(SZI_(G),SZJ_(G)), &
421  intent(in) :: eta_PF_in !< The 2-D eta field (either SSH anomaly
422  !! or column mass anomaly) that was used to calculate the input pressure gradient accelerations
423  !! (or its final value if eta_PF_start is provided, in m or kg m-2.
424  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
425  intent(in) :: U_Cor !< The (3-D) zonal- and meridional-
426  !! velocities or volume or mass fluxes used to calculate the Coriolis
427  !! terms in bc_accel_u and!! bc_accel_v, in m s-1 or m3 s-1 or kg s-1.
428  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
429  intent(in) :: V_Cor !< The (3-D) zonal- and meridional-
430  !! velocities or volume or mass fluxes used to calculate the Coriolis
431  !! terms in bc_accel_u and bc_accel_v, in m s-1 or m3 s-1 or kg s-1.
432  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
433  intent(out) :: accel_layer_u !< The accelerations of each layer
434  !! due to the barotropic calculation, in m s-2.
435  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
436  intent(out) :: accel_layer_v !< The accelerations of each layer
437  !! due to the barotropic calculation, in m s-2.
438  real, dimension(SZI_(G),SZJ_(G)), &
439  intent(inout) :: eta_out !< The final barotropic free surface
440  !! height anomaly or column mass anomaly, in m or kg m-2.
441  real, dimension(SZIB_(G),SZJ_(G)), &
442  intent(out) :: uhbtav !< The barotropic zonal volume or mass
443  !! fluxes averaged through the barotropic steps, in m3 s-1 or kg s-1.
444  real, dimension(SZI_(G),SZJB_(G)), &
445  intent(out) :: vhbtav !< The barotropic meridional volume or
446  !! mass fluxes averaged through the barotropic steps, in m3 s-1 or kg s-1.
447  type(legacy_barotropic_cs), pointer :: CS !< The control structure returned by a
448  !! previous call to barotropic_init.
449  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
450  intent(in), optional :: visc_rem_u !< Both the fraction of the momentum
451  !! originally in a layer that remains after a time-step of viscosity, and the fraction
452  !! of a time-step's worth of a barotropic acceleration that a layer experiences after
453  !! viscosity is applied, in the zonal (_u) and meridional (_v) directions.
454  !! Nondimensional between 0 (at the bottom) and 1 (far above the bottom).
455  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
456  intent(in), optional :: visc_rem_v !< Both the fraction of the momentum
457  !! originally in a layer that remains after a time-step of viscosity, and the fraction
458  !! of a time-step's worth of a barotropic acceleration that a layer experiences after
459  !! viscosity is applied, in the zonal (_u) and meridional (_v) directions.
460  !! Nondimensional between 0 (at the bottom) and 1 (far above the bottom).
461  real, dimension(SZI_(G),SZJ_(G)), &
462  intent(out), optional :: etaav !< The free surface height or column mass
463  !! averaged over the barotropic integration, in m or kg m-2.
464  real, dimension(SZIB_(G),SZJ_(G)), &
465  intent(out), optional :: uhbt_out !< The barotropic zonal volume or mass
466  !! fluxes averaged through the barotropic steps, in m3 s-1 or kg s-1.
467  real, dimension(SZI_(G),SZJB_(G)), &
468  intent(out), optional :: vhbt_out !< The barotropic meridional volume or
469  !! mass fluxes averaged through the barotropic steps, in m3 s-1 or kg s-1.
470  type(ocean_obc_type), &
471  pointer, optional :: OBC !< An open boundary condition type, which
472  !! contains the values associated with open boundary conditions.
473  type(bt_cont_type), &
474  pointer, optional :: BT_cont !< A structure with elements that describe
475  !! the effective open face areas as a function of barotropic flow.
476  real, dimension(:,:), &
477  pointer, optional :: eta_PF_start !< The eta field consistent with the
478  !! pressure gradient at the start of the barotropic stepping, in m or kg m-2.
479  real, dimension(:,:), &
480  pointer, optional :: taux_bot !< The zonal bottom frictional stress
481  !! from ocean to the seafloor, in Pa.
482  real, dimension(:,:), &
483  pointer, optional :: tauy_bot !< The meridional bottom frictional stress
484  !! from ocean to the seafloor, in Pa.
485  real, dimension(:,:,:), &
486  pointer, optional :: uh0, u_uh0
487  real, dimension(:,:,:), &
488  pointer, optional :: vh0, v_vh0
489 
490 ! Arguments: use_fluxes - A logical indicating whether velocities (false) or
491 ! fluxes (true) are used to initialize the barotropic
492 ! velocities.
493 ! (in) U_in - The initial (3-D) zonal velocity or volume or mass fluxes,
494 ! depending on flux_form, in m s-1 or m3 s-1 or kg s-1.
495 ! (in) V_in - The initial (3-D) meridional velocity or volume/mass fluxes,
496 ! depending on flux_form, in m s-1 or m3 s-1 or kg s-1.
497 ! (in) eta_in - The initial barotropic free surface height anomaly or
498 ! column mass anomaly, in m or kg m-2.
499 ! (in) dt - The time increment to integrate over.
500 ! (in) bc_accel_u - The zonal baroclinic accelerations, in m s-2.
501 ! (in) bc_accel_v - The meridional baroclinic accelerations, in m s-2.
502 ! (in) fluxes - A structure containing pointers to any possible
503 ! forcing fields. Unused fields have NULL ptrs.
504 ! (in) pbce - The baroclinic pressure anomaly in each layer
505 ! due to free surface height anomalies, in m2 H-1 s-2.
506 ! (in) eta_PF_in - The 2-D eta field (either SSH anomaly or column mass
507 ! anomaly) that was used to calculate the input pressure
508 ! gradient accelerations (or its final value if
509 ! eta_PF_start is provided, in m or kg m-2.
510 ! Note: eta_in, pbce, and eta_PF_in must have up-to-date halos.
511 ! (in) U_Cor - The (3-D) zonal- and meridional- velocities or volume or
512 ! (in) V_Cor mass fluxes used to calculate the Coriolis terms in
513 ! bc_accel_u and bc_accel_v, in m s-1 or m3 s-1 or kg s-1.
514 ! (out) accel_layer_u - The accelerations of each layer due to the
515 ! (out) accel_layer_v - barotropic calculation, in m s-2.
516 ! (out) eta_out - The final barotropic free surface height anomaly or
517 ! column mass anomaly, in m or kg m-2.
518 ! (out) uhbtav - the barotropic zonal volume or mass fluxes averaged
519 ! through the barotropic steps, in m3 s-1 or kg s-1.
520 ! (out) vhbtav - the barotropic meridional volume or mass fluxes averaged
521 ! through the barotropic steps, in m3 s-1 or kg s-1.
522 ! (in) G - The ocean's grid structure.
523 ! (in) GV - The ocean's vertical grid structure.
524 ! (in) CS - The control structure returned by a previous call to
525 ! barotropic_init.
526 ! (in,opt) visc_rem_u - Both the fraction of the momentum originally in a
527 ! (in,opt) visc_rem_v - layer that remains after a time-step of viscosity,
528 ! and the fraction of a time-step's worth of a
529 ! barotropic acceleration that a layer experiences
530 ! after viscosity is applied, in the zonal (_u) and
531 ! meridional (_v) directions. Nondimensional between
532 ! 0 (at the bottom) and 1 (far above the bottom).
533 ! (out,opt) etaav - The free surface height or column mass averaged over the
534 ! barotropic integration, in m or kg m-2.
535 ! (out,opt) uhbt_out - The barotropic zonal volume or mass fluxes at the end
536 ! of the barotropic steps, in m3 s-1 or kg s-1.
537 ! (out,opt) vhbt_out - The barotropic meridional volume or mass fluxes at the
538 ! end of the barotropic steps, in m3 s-1 or kg s-1.
539 ! (in,opt) OBC - An open boundary condition type, which contains the values
540 ! associated with open boundary conditions.
541 ! (in,opt) BT_cont - A structure with elements that describe the effective
542 ! open face areas as a function of barotropic flow.
543 ! (in,opt) eta_PF_start - The eta field consistent with the pressure gradient
544 ! at the start of the barotropic stepping, in m or kg m-2.
545 ! (in,opt) taux_bot - The zonal bottom frictional stress from ocean to the
546 ! seafloor, in Pa.
547 ! (in,opt) tauy_bot - The meridional bottom frictional stress from ocean to
548 ! the seafloor, in Pa.
549 
550 ! This subroutine time steps the barotropic equations explicitly.
551 ! For gravity waves, anything between a forwards-backwards scheme
552 ! and a simulated backwards Euler scheme is used, with bebt between
553 ! 0.0 and 1.0 determining the scheme. In practice, bebt must be of
554 ! order 0.2 or greater. A forwards-backwards treatment of the
555 ! Coriolis terms is always used.
556 ! Depending on the value of use_fluxes, the initial velocities are determined
557 ! from input velocites or volume (Boussinesq) or mass (non-Boussinesq) fluxes.
558 
559  real :: ubt_Cor(szib_(g),szj_(g)) ! The barotropic velocities that had been
560  real :: vbt_Cor(szi_(g),szjb_(g)) ! use to calculate the input Coriolis
561  ! terms, in m s-1.
562  real :: wt_u(szib_(g),szj_(g),szk_(g)) ! wt_u and wt_v are the
563  real :: wt_v(szi_(g),szjb_(g),szk_(g)) ! normalized weights to
564  ! be used in calculating barotropic velocities, possibly with
565  ! sums less than one due to viscous losses. Nondimensional.
566  real, dimension(SZIB_(G),SZJ_(G)) :: &
567  av_rem_u, & ! The weighted average of visc_rem_u, if it is present. ND.
568  tmp_u ! A temporary array at u points.
569  real, dimension(SZI_(G),SZJB_(G)) :: &
570  av_rem_v, & ! The weighted average of visc_rem_u, if it is present. ND.
571  tmp_v ! A temporary array at v points.
572  real, dimension(SZI_(G),SZJ_(G)) :: &
573  e_anom ! The anomaly in the sea surface height or column mass
574  ! averaged between the beginning and end of the time step,
575  ! relative to eta_PF, with SAL effects included, in units
576  ! of H (m or kg m-2, the same as eta and h).
577 
578  ! These are always allocated with symmetric memory and wide halos.
579  real :: q(szibw_(cs),szjbw_(cs)) ! A pseudo potential vorticity in s-1 m-1.
580  real, dimension(SZIBW_(CS),SZJW_(CS)) :: &
581  ubt, & ! The zonal barotropic velocity in m s-1.
582  bt_rem_u, & ! The fraction of the barotropic zonal velocity that remains
583  ! after a time step, the remainder being lost to bottom drag.
584  ! bt_rem_u is a nondimensional number between 0 and 1.
585  bt_force_u, & ! The vertical average of all of the u-accelerations that are
586  ! not explicitly included in the barotropic equation, m s-2.
587  u_accel_bt, & ! The difference between the zonal acceleration from the
588  ! barotropic calculation and BT_force_u, in m s-2.
589  uhbt, & ! The zonal barotropic thickness fluxes, in H m2 s-1.
590  uhbt0, & ! The difference between the sum of the layer zonal thickness
591  ! fluxes and the barotropic thickness flux using the same
592  ! velocity, in H m2 s-1.
593  ubt_old, & ! The starting value of ubt in a barotropic step, in m s-1.
594  ubt_sum, & ! The sum of ubt over the time steps, in m s-1.
595  uhbt_sum, & ! The sum of uhbt over the time steps, in H m2 s-1.
596  ubt_wtd, & ! A weighted sum used to find the filtered final ubt, in m s-1.
597  ubt_trans, & ! The latest value of ubt used for a transport, in m s-1.
598  azon, bzon, & ! _zon & _mer are the values of the Coriolis force which
599  czon, dzon, & ! are applied to the neighboring values of vbtav & ubtav,
600  amer, bmer, & ! respectively to get the barotropic inertial rotation,
601  cmer, dmer, & ! in units of s-1.
602  cor_ref_u, & ! The zonal barotropic Coriolis acceleration due
603  ! to the reference velocities, in m s-2.
604  pfu_bt_sum, & ! The summed zonal barotropic pressure gradient force, in m s-2.
605  coru_bt_sum, & ! The summed zonal barotropic Coriolis acceleration, in m s-2.
606  dcor_u, & ! A simply averaged depth at u points, in m.
607  datu ! Basin depth at u-velocity grid points times the y-grid
608  ! spacing, in H m.
609  real, dimension(SZIW_(CS),SZJBW_(CS)) :: &
610  vbt, & ! The meridional barotropic velocity in m s-1.
611  bt_rem_v, & ! The fraction of the barotropic meridional velocity that
612  ! remains after a time step, the rest being lost to bottom
613  ! drag. bt_rem_v is a nondimensional number between 0 and 1.
614  bt_force_v, & ! The vertical average of all of the v-accelerations that are
615  ! not explicitly included in the barotropic equation, m s-2.
616  v_accel_bt, & ! The difference between the meridional acceleration from the
617  ! barotropic calculation and BT_force_v, in m s-2.
618  vhbt, & ! The meridional barotropic thickness fluxes, in H m2 s-1.
619  vhbt0, & ! The difference between the sum of the layer meridional
620  ! thickness fluxes and the barotropic thickness flux using
621  ! the same velocities, in H m2 s-1.
622  vbt_old, & ! The starting value of vbt in a barotropic step, in m s-1.
623  vbt_sum, & ! The sum of vbt over the time steps, in m s-1.
624  vhbt_sum, & ! The sum of vhbt over the time steps, in H m2 s-1.
625  vbt_wtd, & ! A weighted sum used to find the filtered final vbt, in m s-1.
626  vbt_trans, & ! The latest value of vbt used for a transport, in m s-1.
627  cor_ref_v, & ! The meridional barotropic Coriolis acceleration due
628  ! to the reference velocities, in m s-2.
629  pfv_bt_sum, & ! The summed meridional barotropic pressure gradient force,
630  ! in m s-2.
631  corv_bt_sum, & ! The summed meridional barotropic Coriolis acceleration,
632  ! in m s-2.
633  dcor_v, & ! A simply averaged depth at v points, in m.
634  datv ! Basin depth at v-velocity grid points times the x-grid
635  ! spacing, in H m.
636  real, target, dimension(SZIW_(CS),SZJW_(CS)) :: &
637  eta, & ! The barotropic free surface height anomaly or column mass
638  ! anomaly, in m or kg m-2.
639  eta_pred ! A predictor value of eta, in m or kg m-2 like eta.
640  real, pointer, dimension(:,:) :: &
641  eta_PF_BT ! A pointer to the eta array (either eta or eta_pred) that
642  ! determines the barotropic pressure force, in m or kg m-2.
643  real, dimension(SZIW_(CS),SZJW_(CS)) :: &
644  eta_sum, & ! eta summed across the timesteps, in m or kg m-2.
645  eta_wtd, & ! A weighted estimate used to calculate eta_out, in m or kg m-2.
646  eta_PF, & ! A local copy of the 2-D eta field (either SSH anomaly or
647  ! column mass anomaly) that was used to calculate the input
648  ! pressure gradient accelerations, in m or kg m-2.
649  eta_pf_1, & ! The initial value of eta_PF, when interp_eta_PF is
650  ! true, in m or kg m-2.
651  d_eta_pf, & ! The change in eta_PF over the barotropic time stepping when
652  ! interp_eta_PF is true, in m or kg m-2.
653  gtot_e, & ! gtot_X is the effective total reduced gravity used to relate
654  gtot_w, & ! free surface height deviations to pressure forces (including
655  gtot_n, & ! GFS and baroclinic contributions) in the barotropic momentum
656  gtot_s, & ! equations half a grid-point in the X-direction (X is N, S,
657  ! E, or W) from the thickness point. gtot_X has units of m2 H-1 s-2.
658  ! (See Hallberg, J Comp Phys 1997 for a discussion.)
659  eta_src, & ! The source of eta per barotropic timestep, in m or kg m-2.
660  dyn_coef_eta, & ! The coefficient relating the changes in eta to the
661  ! dynamic surface pressure under rigid ice, in m2 s-2 H-1.
662  p_surf_dyn ! A dynamic surface pressure under rigid ice, in m2 s-2.
663  type(local_bt_cont_u_type), dimension(SZIBW_(CS),SZJW_(CS)) :: &
664  BTCL_u ! A repackaged version of the u-point information in BT_cont.
665  type(local_bt_cont_v_type), dimension(SZIW_(CS),SZJBW_(CS)) :: &
666  BTCL_v ! A repackaged version of the v-point information in BT_cont.
667  ! End of wide-sized variables.
668 
669  real :: I_Rho0 ! The inverse of the mean density (Rho0), in m3 kg-1.
670  real :: visc_rem ! A work variable that may equal visc_rem_[uv]. Nondim.
671  real :: vel_prev ! The previous velocity in m s-1.
672  real :: vel_trans ! The combination of the previous and current velocity
673  ! that does the mass transport, in m s-1.
674  real :: dtbt ! The barotropic time step in s.
675  real :: bebt ! A copy of CS%bebt.
676  real :: be_proj ! The fractional amount by which velocities are projected
677  ! when project_velocity is true. For now be_proj is set
678  ! to equal bebt, as they have similar roles and meanings.
679  real :: Idt ! The inverse of dt, in s-1.
680  real :: det_de ! The partial derivative due to self-attraction and loading
681  ! of the reference geopotential with the sea surface height.
682  ! This is typically ~0.09 or less.
683  real :: dgeo_de ! The constant of proportionality between geopotential and
684  ! sea surface height. It is a nondimensional number of
685  ! order 1. For stability, this may be made larger
686  ! than physical problem would suggest.
687  real :: Instep ! The inverse of the number of barotropic time steps
688  ! to take.
689  real :: Cor, gradP ! The Coriolis and pressure gradient accelerations, m s-1.
690  real :: wt_end ! The weighting of the final value of eta_PF, ND.
691  integer :: nstep ! The number of barotropic time steps to take.
692  type(time_type) :: &
693  time_bt_start, & ! The starting time of the barotropic steps.
694  time_step_end, & ! The end time of a barotropic step.
695  time_end_in ! The end time for diagnostics when this routine started.
696  real :: time_int_in ! The diagnostics' time interval when this routine started.
697  logical :: do_hifreq_output ! If true, output occurs every barotropic step.
698  logical :: use_visc_rem, use_BT_cont
699  logical :: do_ave, find_etaav, find_PF, find_Cor
700  logical :: ice_is_rigid, nonblock_setup, interp_eta_PF
701  logical :: project_velocity, add_uh0
702 
703  real :: dyn_coef_max ! The maximum stable value of dyn_coef_eta, in m2 s-2 H-1.
704  real :: ice_strength = 0.0 ! The effective strength of the ice in m s-2.
705  real :: Idt_max2 ! The squared inverse of the local maximum stable
706  ! barotropic time step, in s-2.
707  real :: H_min_dyn ! The minimum depth to use in limiting the size of the
708  ! dynamic surface pressure for stability, in H.
709  real :: H_eff_dx2 ! The effective total thickness divided by the grid spacing
710  ! squared, in H m-2.
711  real :: vel_tmp ! A temporary velocity, in m s-1.
712 
713  real, allocatable, dimension(:) :: wt_vel, wt_eta, wt_accel, wt_trans, wt_accel2
714  real :: sum_wt_vel, sum_wt_eta, sum_wt_accel, sum_wt_trans
715  real :: I_sum_wt_vel, I_sum_wt_eta, I_sum_wt_accel, I_sum_wt_trans
716  real :: dt_filt ! The half-width of the barotropic filter, in s.
717  integer :: nfilter
718 
719  logical :: apply_OBCs, apply_OBC_flather
720  type(bt_obc_type) :: BT_OBC ! A structure with all of this module's fields
721  ! for applying open boundary conditions.
722  type(memory_size_type) :: MS
723  character(len=200) :: mesg
724  integer :: pid_ubt, pid_eta, pid_e_anom, pid_etaav, pid_uhbtav, pid_ubtav
725  integer :: pid_q, pid_eta_PF, pid_dyn_coef_eta, pid_eta_src
726  integer :: pid_DCor_u, pid_Datu_res, pid_tmp_u, pid_gtot_E, pid_gtot_W
727  integer :: pid_bt_rem_u, pid_Datu, pid_BT_force_u, pid_Cor_ref
728  integer :: pid_eta_PF_1, pid_d_eta_PF, pid_uhbt0
729  integer :: isv, iev, jsv, jev ! The valid array size at the end of a step.
730  integer :: stencil ! The stencil size of the algorithm, often 1 or 2.
731  integer :: isvf, ievf, jsvf, jevf, num_cycles
732  integer :: i, j, k, n
733  integer :: is, ie, js, je, nz, Isq, Ieq, Jsq, Jeq
734  integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB
735 
736  if (.not.associated(cs)) call mom_error(fatal, &
737  "legacy_btstep: Module MOM_legacy_barotropic must be initialized before it is used.")
738  if (.not.cs%split) return
739  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
740  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
741  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
742  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
743  ms%isdw = cs%isdw ; ms%iedw = cs%iedw ; ms%jsdw = cs%jsdw ; ms%jedw = cs%jedw
744  idt = 1.0 / dt
745 
746  use_bt_cont = .false.
747  if (present(bt_cont)) use_bt_cont = (associated(bt_cont))
748 
749  interp_eta_pf = .false.
750  if (present(eta_pf_start)) interp_eta_pf = (associated(eta_pf_start))
751 
752  project_velocity = cs%BT_project_velocity
753 
754  ! Figure out the fullest arrays that could be updated.
755  stencil = 1
756  if ((.not.use_bt_cont) .and. cs%Nonlinear_continuity .and. &
757  (cs%Nonlin_cont_update_period > 0)) stencil = 2
758 
759  num_cycles = 1
760  if (cs%use_wide_halos) &
761  num_cycles = min((is-cs%isdw) / stencil, (js-cs%jsdw) / stencil)
762  isvf = is - (num_cycles-1)*stencil ; ievf = ie + (num_cycles-1)*stencil
763  jsvf = js - (num_cycles-1)*stencil ; jevf = je + (num_cycles-1)*stencil
764 
765  do_ave = query_averaging_enabled(cs%diag)
766  find_etaav = present(etaav)
767  use_visc_rem = present(visc_rem_u)
768  if ((use_visc_rem) .neqv. present(visc_rem_v)) call mom_error(fatal, &
769  "btstep: Either both visc_rem_u and visc_rem_v or neither"// &
770  " one must be present in call to btstep.")
771  find_pf = (do_ave .and. ((cs%id_PFu_bt > 0) .or. (cs%id_PFv_bt > 0)))
772  find_cor = (do_ave .and. ((cs%id_Coru_bt > 0) .or. (cs%id_Corv_bt > 0)))
773 
774  add_uh0 = .false.
775  if (present(uh0)) add_uh0 = associated(uh0)
776  if (add_uh0 .and. .not.(present(vh0) .and. present(u_uh0) .and. &
777  present(v_vh0))) call mom_error(fatal, &
778  "legacy_btstep: vh0, u_uh0, and v_vh0 must be present if uh0 is used.")
779  if (add_uh0 .and. .not.(associated(vh0) .and. associated(u_uh0) .and. &
780  associated(v_vh0))) call mom_error(fatal, &
781  "legacy_btstep: vh0, u_uh0, and v_vh0 must be associated if uh0 is used.")
782  if (add_uh0 .and. use_fluxes) call mom_error(warning, &
783  "legacy_btstep: with use_fluxes, add_uh0 does nothing!")
784  if (use_fluxes) add_uh0 = .false.
785 
786  ! This can be changed to try to optimize the performance.
787  nonblock_setup = g%nonblocking_updates
788 
789  if (id_clock_calc_pre > 0) call cpu_clock_begin(id_clock_calc_pre)
790 
791  apply_obcs = .false. ; apply_u_obcs = .false. ; apply_v_obcs = .false.
792  apply_obc_flather = .false.
793  if (present(obc)) then ; if (associated(obc)) then
794  apply_u_obcs = obc%Flather_u_BCs_exist_globally .or. obc%specified_u_BCs_exist_globally
795  apply_v_obcs = obc%Flather_v_BCs_exist_globally .or. obc%specified_v_BCs_exist_globally
796  apply_obc_flather = obc%Flather_u_BCs_exist_globally .or. obc%Flather_v_BCs_exist_globally
797  apply_obcs = obc%specified_u_BCs_exist_globally .or. obc%specified_v_BCs_exist_globally .or. apply_obc_flather
798 
799  if (apply_obc_flather .and. .not.gv%Boussinesq) call mom_error(fatal, &
800  "legacy_btstep: Flather open boundary conditions have not yet been "// &
801  "implemented for a non-Boussinesq model.")
802  endif ; endif
803 
804  nstep = ceiling(dt/cs%dtbt - 0.0001)
805  if (is_root_pe() .and. (nstep /= cs%nstep_last)) then
806  write(mesg,'("legacy_btstep is using a dynamic barotropic timestep of ", ES12.6, &
807  & " seconds, max ", ES12.6, ".")') (dt/nstep), cs%dtbt_max
808  call mom_mesg(mesg, 3)
809  endif
810  cs%nstep_last = nstep
811 
812  ! Set the actual barotropic time step.
813  instep = 1.0 / real(nstep)
814  dtbt = dt * instep
815  bebt = cs%bebt
816  be_proj = cs%bebt
817  i_rho0 = 1.0/gv%Rho0
818  do_ave = query_averaging_enabled(cs%diag)
819 
820  do_hifreq_output = .false.
821  if ((cs%id_ubt_hifreq > 0) .or. (cs%id_vbt_hifreq > 0) .or. &
822  (cs%id_eta_hifreq > 0) .or. (cs%id_eta_pred_hifreq > 0) .or. &
823  (cs%id_uhbt_hifreq > 0) .or. (cs%id_vhbt_hifreq > 0)) then
824  do_hifreq_output = query_averaging_enabled(cs%diag, time_int_in, time_end_in)
825  if (do_hifreq_output) &
826  time_bt_start = time_end_in - set_time(int(floor(dt+0.5)))
827  endif
828 
829 ! Calculate the constant coefficients for the Coriolis force terms in the
830 ! barotropic momentum equations. This has to be done quite early to start
831 ! the halo update that needs to be completed before the next calculations.
832  if (cs%linearized_BT_PV) then
833 !$OMP parallel do default(none) shared(jsvf,jevf,isvf,ievf,q,CS)
834  do j=jsvf-2,jevf+1 ; do i=isvf-2,ievf+1
835  q(i,j) = cs%q_D(i,j)
836  enddo ; enddo
837 !$OMP parallel do default(none) shared(jsvf,jevf,isvf,ievf,DCor_u,CS)
838  do j=jsvf-1,jevf+1 ; do i=isvf-2,ievf+1
839  dcor_u(i,j) = cs%D_u_Cor(i,j)
840  enddo ; enddo
841 !$OMP parallel do default(none) shared(jsvf,jevf,isvf,ievf,DCor_v,CS)
842  do j=jsvf-2,jevf+1 ; do i=isvf-1,ievf+1
843  dcor_v(i,j) = cs%D_v_Cor(i,j)
844  enddo ; enddo
845  else
846  q(:,:) = 0.0 ; dcor_u(:,:) = 0.0 ; dcor_v(:,:) = 0.0
847  ! This option has not yet been written properly.
848  ! D here should be replaced with D+eta(Bous) or eta(non-Bous).
849 !$OMP parallel do default(none) shared(js,je,is,ie,DCor_u,G)
850  do j=js,je ; do i=is-1,ie
851  dcor_u(i,j) = 0.5 * (g%bathyT(i+1,j) + g%bathyT(i,j))
852  enddo ; enddo
853 !$OMP parallel do default(none) shared(js,je,is,ie,DCor_v,G)
854  do j=js-1,je ; do i=is,ie
855  dcor_v(i,j) = 0.5 * (g%bathyT(i,j+1) + g%bathyT(i,j))
856  enddo ; enddo
857 !$OMP parallel do default(none) shared(js,je,is,ie,q,G)
858  do j=js-1,je ; do i=is-1,ie
859  q(i,j) = 0.25 * g%CoriolisBu(i,j) * &
860  ((g%areaT(i,j) + g%areaT(i+1,j+1)) + (g%areaT(i+1,j) + g%areaT(i,j+1))) / &
861  ((g%areaT(i,j) * g%bathyT(i,j) + g%areaT(i+1,j+1) * g%bathyT(i+1,j+1)) + &
862  (g%areaT(i+1,j) * g%bathyT(i+1,j) + g%areaT(i,j+1) * g%bathyT(i,j+1)))
863  enddo ; enddo
864  ! With very wide halos, q and D need to be calculated on the available data
865  ! domain and then updated onto the full computational domain.
866  ! These calculations can be done almost immediately, but the halo updates
867  ! must be done before the [abcd]mer and [abcd]zon are calculated.
868  if (id_clock_calc_pre > 0) call cpu_clock_end(id_clock_calc_pre)
869  if (id_clock_pass_pre > 0) call cpu_clock_begin(id_clock_pass_pre)
870  if (nonblock_setup) then
871  pid_q = pass_var_start(q, cs%BT_Domain, to_all, position=corner)
872  pid_dcor_u = pass_vector_start(dcor_u, dcor_v, cs%BT_Domain, to_all+scalar_pair)
873  else
874  call pass_var(q, cs%BT_Domain, to_all, position=corner)
875  call pass_vector(dcor_u, dcor_v, cs%BT_Domain, to_all+scalar_pair)
876  endif
877  if (id_clock_pass_pre > 0) call cpu_clock_end(id_clock_pass_pre)
878  if (id_clock_calc_pre > 0) call cpu_clock_begin(id_clock_calc_pre)
879  endif
880 
881  if (nonblock_setup) then
882  ! Start all halo updates that are ready to go.
883  !### if (use_BT_cont) call start_set_local_BT_cont_types( ... )
884  if ((.not.use_bt_cont) .and. cs%rescale_D_bt .and. (ievf>ie)) then
885  if (id_clock_calc_pre > 0) call cpu_clock_end(id_clock_calc_pre)
886  if (id_clock_pass_pre > 0) call cpu_clock_begin(id_clock_pass_pre)
887  pid_datu_res = pass_vector_start(cs%Datu_res, cs%Datv_res, cs%BT_Domain, &
888  to_all+scalar_pair)
889  if (id_clock_pass_pre > 0) call cpu_clock_end(id_clock_pass_pre)
890  if (id_clock_calc_pre > 0) call cpu_clock_begin(id_clock_calc_pre)
891  endif
892  endif
893 
894  ! Zero out various wide-halo arrays.
895  do j=cs%jsdw,cs%jedw ; do i=cs%isdw,cs%iedw
896  gtot_e(i,j) = 0.0 ; gtot_w(i,j) = 0.0
897  gtot_n(i,j) = 0.0 ; gtot_s(i,j) = 0.0
898  eta(i,j) = 0.0
899  eta_pf(i,j) = 0.0
900  if (interp_eta_pf) then
901  eta_pf_1(i,j) = 0.0 ; d_eta_pf(i,j) = 0.0
902  endif
903  p_surf_dyn(i,j) = 0.0
904  if (cs%dynamic_psurf) dyn_coef_eta(i,j) = 0.0
905  enddo ; enddo
906  ! The halo regions of various arrays need to be initialized to
907  ! non-NaNs in case the neighboring domains are not part of the ocean.
908  ! Otherwise a halo update later on fills in the correct values.
909  do j=cs%jsdw,cs%jedw ; do i=cs%isdw-1,cs%iedw
910  cor_ref_u(i,j) = 0.0 ; bt_force_u(i,j) = 0.0 ; ubt(i,j) = 0.0
911  datu(i,j) = 0.0 ; bt_rem_u(i,j) = 0.0 ; uhbt0(i,j) = 0.0
912  enddo ; enddo
913  do j=cs%jsdw-1,cs%jedw ; do i=cs%isdw,cs%iedw
914  cor_ref_v(i,j) = 0.0 ; bt_force_v(i,j) = 0.0 ; vbt(i,j) = 0.0
915  datv(i,j) = 0.0 ; bt_rem_v(i,j) = 0.0 ; vhbt0(i,j) = 0.0
916  enddo ; enddo
917 
918  ! Copy input arrays into their wide-halo counterparts. eta_in and eta_PF_in
919  ! have the correct values in their halo regions.
920  if (interp_eta_pf) then
921  do j=g%jsd,g%jed ; do i=g%isd,g%ied
922  eta(i,j) = eta_in(i,j)
923  eta_pf_1(i,j) = eta_pf_start(i,j)
924  d_eta_pf(i,j) = eta_pf_in(i,j) - eta_pf_start(i,j)
925  enddo ; enddo
926  else
927  do j=g%jsd,g%jed ; do i=g%isd,g%ied
928  eta(i,j) = eta_in(i,j)
929  eta_pf(i,j) = eta_pf_in(i,j)
930  enddo ; enddo
931  endif
932 
933  if (use_visc_rem) then
934 !$OMP parallel do default(none) shared(Isq,Ieq,js,je,nz,visc_rem_u,Instep,wt_u,CS) private(visc_rem)
935  do k=1,nz ; do j=js-1,je+1 ; do i=isq-1,ieq+1
936  ! rem needs greater than visc_rem_u and 1-Instep/visc_rem_u.
937  ! The 0.5 below is just for safety.
938  if (visc_rem_u(i,j,k) <= 0.0) then ; visc_rem = 0.0
939  elseif (visc_rem_u(i,j,k) >= 1.0) then ; visc_rem = 1.0
940  elseif (visc_rem_u(i,j,k)**2 > visc_rem_u(i,j,k) - 0.5*instep) then
941  visc_rem = visc_rem_u(i,j,k)
942  else ; visc_rem = 1.0 - 0.5*instep/visc_rem_u(i,j,k) ; endif
943  wt_u(i,j,k) = cs%frhatu(i,j,k) * visc_rem
944  enddo ; enddo ; enddo
945 !$OMP parallel do default(none) shared(is,ie,Jsq,Jeq,nz,visc_rem_v,Instep,wt_v,CS) private(visc_rem)
946  do k=1,nz ; do j=jsq-1,jeq+1 ; do i=is-1,ie+1
947  ! rem needs greater than visc_rem_v and 1-Instep/visc_rem_v.
948  if (visc_rem_v(i,j,k) <= 0.0) then ; visc_rem = 0.0
949  elseif (visc_rem_v(i,j,k) >= 1.0) then ; visc_rem = 1.0
950  elseif (visc_rem_v(i,j,k)**2 > visc_rem_v(i,j,k) - 0.5*instep) then
951  visc_rem = visc_rem_v(i,j,k)
952  else ; visc_rem = 1.0 - 0.5*instep/visc_rem_v(i,j,k) ; endif
953  wt_v(i,j,k) = cs%frhatv(i,j,k) * visc_rem
954  enddo ; enddo ; enddo
955  else
956  do k=1,nz ; do j=js-1,je+1 ; do i=isq-1,ieq+1
957  wt_u(i,j,k) = cs%frhatu(i,j,k)
958  enddo ; enddo ; enddo
959  do k=1,nz ; do j=jsq-1,jeq+1 ; do i=is-1,ie+1
960  wt_v(i,j,k) = cs%frhatv(i,j,k)
961  enddo ; enddo ; enddo
962  endif
963 
964  ! The gtot arrays are the effective layer-weighted reduced gravities for
965  ! accelerations across the various faces, with names for the relative
966  ! locations of the faces to the pressure point. They will have their halos
967  ! updated later on.
968  do k=1,nz
969  do j=js,je ; do i=is-1,ie
970  gtot_e(i,j) = gtot_e(i,j) + pbce(i,j,k) * wt_u(i,j,k)
971  gtot_w(i+1,j) = gtot_w(i+1,j) + pbce(i+1,j,k) * wt_u(i,j,k)
972  enddo ; enddo
973  do j=js-1,je ; do i=is,ie
974  gtot_n(i,j) = gtot_n(i,j) + pbce(i,j,k) * wt_v(i,j,k)
975  gtot_s(i,j+1) = gtot_s(i,j+1) + pbce(i,j+1,k) * wt_v(i,j,k)
976  enddo ; enddo
977  enddo
978 
979  if (cs%tides) then
980  call tidal_forcing_sensitivity(g, cs%tides_CSp, det_de)
981  dgeo_de = 1.0 + det_de + cs%G_extra
982  else
983  dgeo_de = 1.0 + cs%G_extra
984  endif
985 
986  if (nonblock_setup .and. .not.cs%linearized_BT_PV) then
987  if (id_clock_calc_pre > 0) call cpu_clock_end(id_clock_calc_pre)
988  if (id_clock_pass_pre > 0) call cpu_clock_begin(id_clock_pass_pre)
989  call pass_var_complete(pid_q, q, cs%BT_Domain, to_all, position=corner)
990  call pass_vector_complete(pid_dcor_u, dcor_u, dcor_v, cs%BT_Domain, to_all+scalar_pair)
991  if (id_clock_pass_pre > 0) call cpu_clock_end(id_clock_pass_pre)
992  if (id_clock_calc_pre > 0) call cpu_clock_begin(id_clock_calc_pre)
993  endif
994 
995  ! Calculate the open areas at the velocity points.
996  ! The halo updates are needed before Datu is first used, either in set_up_BT_OBC or ubt_Cor.
997  if (use_bt_cont) then
998  call set_local_bt_cont_types(bt_cont, btcl_u, btcl_v, g, ms, cs%BT_Domain, 1+ievf-ie)
999  else
1000  if (cs%rescale_D_bt .and. (ievf>ie)) then
1001  ! Datu_res was previously calculated in btcalc, and will be used in find_face_areas.
1002  ! This halo update is needed for wider halos than 1. The complete goes here.
1003  if (id_clock_calc_pre > 0) call cpu_clock_end(id_clock_calc_pre)
1004  if (id_clock_pass_pre > 0) call cpu_clock_begin(id_clock_pass_pre)
1005  if (nonblock_setup) then
1006  call pass_vector_complete(pid_datu_res, cs%Datu_res, cs%Datv_res, &
1007  cs%BT_Domain, to_all+scalar_pair)
1008  else
1009  call pass_vector(cs%Datu_res, cs%Datv_res, cs%BT_Domain, to_all+scalar_pair)
1010  endif
1011  if (id_clock_pass_pre > 0) call cpu_clock_end(id_clock_pass_pre)
1012  if (id_clock_calc_pre > 0) call cpu_clock_begin(id_clock_calc_pre)
1013  endif
1014  if (cs%Nonlinear_continuity) then
1015  call find_face_areas(datu, datv, g, gv, cs, ms, cs%rescale_D_bt, eta, 1)
1016  else
1017  call find_face_areas(datu, datv, g, gv, cs, ms, cs%rescale_D_bt, halo=1)
1018  endif
1019  endif
1020 
1021  ! Set up fields related to the open boundary conditions.
1022  if (apply_obcs) then
1023  call set_up_bt_obc(obc, eta, bt_obc, g, gv, ms, ievf-ie, use_bt_cont, &
1024  datu, datv, btcl_u, btcl_v)
1025  endif
1026 
1027 ! Here the vertical average accelerations due to the Coriolis, advective,
1028 ! pressure gradient and horizontal viscous terms in the layer momentum
1029 ! equations are calculated. These will be used to determine the difference
1030 ! between the accelerations due to the average of the layer equations and the
1031 ! barotropic calculation.
1032  ! ### Should IDatu here be replaced with 1/D+eta(Bous) or 1/eta(non-Bous)?
1033  if (use_visc_rem) then
1034  do j=js,je ; do i=is-1,ie
1035  bt_force_u(i,j) = fluxes%taux(i,j) * i_rho0*cs%IDatu(i,j)*visc_rem_u(i,j,1)
1036  enddo ; enddo
1037  do j=js-1,je ; do i=is,ie
1038  bt_force_v(i,j) = fluxes%tauy(i,j) * i_rho0*cs%IDatv(i,j)*visc_rem_v(i,j,1)
1039  enddo ; enddo
1040  else
1041  do j=js,je ; do i=is-1,ie
1042  bt_force_u(i,j) = fluxes%taux(i,j) * i_rho0 * cs%IDatu(i,j)
1043  enddo ; enddo
1044  do j=js-1,je ; do i=is,ie
1045  bt_force_v(i,j) = fluxes%tauy(i,j) * i_rho0 * cs%IDatv(i,j)
1046  enddo ; enddo
1047  endif
1048  if (present(taux_bot) .and. present(tauy_bot)) then
1049  if (associated(taux_bot) .and. associated(tauy_bot)) then
1050  do j=js,je ; do i=is-1,ie
1051  bt_force_u(i,j) = bt_force_u(i,j) - taux_bot(i,j) * i_rho0 * cs%IDatu(i,j)
1052  enddo ; enddo
1053  do j=js-1,je ; do i=is,ie
1054  bt_force_v(i,j) = bt_force_v(i,j) - tauy_bot(i,j) * i_rho0 * cs%IDatv(i,j)
1055  enddo ; enddo
1056  endif
1057  endif
1058 
1059  ! bc_accel_u & bc_accel_v are only available on the potentially
1060  ! non-symmetric computational domain.
1061  do k=1,nz ; do j=js,je ; do i=isq,ieq
1062  bt_force_u(i,j) = bt_force_u(i,j) + wt_u(i,j,k) * bc_accel_u(i,j,k)
1063  enddo ; enddo ; enddo
1064  do k=1,nz ; do j=jsq,jeq ; do i=is,ie
1065  bt_force_v(i,j) = bt_force_v(i,j) + wt_v(i,j,k) * bc_accel_v(i,j,k)
1066  enddo ; enddo ; enddo
1067 
1068  ! Determine the difference between the sum of the layer fluxes and the
1069  ! barotropic fluxes found from the same input velocities.
1070  if (add_uh0) then
1071  do j=js,je ; do i=is-1,ie ; uhbt(i,j) = 0.0 ; ubt(i,j) = 0.0 ; enddo ; enddo
1072  do j=js-1,je ; do i=is,ie ; vhbt(i,j) = 0.0 ; vbt(i,j) = 0.0 ; enddo ; enddo
1073  do k=1,nz ; do j=js,je ; do i=is-1,ie
1074  uhbt(i,j) = uhbt(i,j) + uh0(i,j,k)
1075  ubt(i,j) = ubt(i,j) + wt_u(i,j,k) * u_uh0(i,j,k)
1076  enddo ; enddo ; enddo
1077  do k=1,nz ; do j=js-1,je ; do i=is,ie
1078  vhbt(i,j) = vhbt(i,j) + vh0(i,j,k)
1079  vbt(i,j) = vbt(i,j) + wt_v(i,j,k) * v_vh0(i,j,k)
1080  enddo ; enddo ; enddo
1081  if (use_bt_cont) then
1082  do j=js,je ; do i=is-1,ie
1083  uhbt0(i,j) = uhbt(i,j) - find_uhbt(ubt(i,j),btcl_u(i,j))
1084  enddo ; enddo
1085  do j=js-1,je ; do i=is,ie
1086  vhbt0(i,j) = vhbt(i,j) - find_vhbt(vbt(i,j),btcl_v(i,j))
1087  enddo ; enddo
1088  else
1089  do j=js,je ; do i=is-1,ie
1090  uhbt0(i,j) = uhbt(i,j) - datu(i,j)*ubt(i,j)
1091  enddo ; enddo
1092  do j=js-1,je ; do i=is,ie
1093  vhbt0(i,j) = vhbt(i,j) - datv(i,j)*vbt(i,j)
1094  enddo ; enddo
1095  endif
1096  endif
1097 
1098 ! Calculate the initial barotropic velocities from the layer's velocities.
1099  do j=jsvf-1,jevf+1 ; do i=isvf-2,ievf+1
1100  ubt(i,j) = 0.0 ; uhbt(i,j) = 0.0 ; u_accel_bt(i,j) = 0.0
1101  enddo ; enddo
1102  do j=jsvf-2,jevf+1 ; do i=isvf-1,ievf+1
1103  vbt(i,j) = 0.0 ; vhbt(i,j) = 0.0 ; v_accel_bt(i,j) = 0.0
1104  enddo ; enddo
1105  if (use_fluxes) then
1106  do k=1,nz ; do j=js,je ; do i=is-1,ie
1107  uhbt(i,j) = uhbt(i,j) + u_in(i,j,k)
1108  enddo ; enddo ; enddo
1109  do k=1,nz ; do j=js-1,je ; do i=is,ie
1110  vhbt(i,j) = vhbt(i,j) + v_in(i,j,k)
1111  enddo ; enddo ; enddo
1112  if (use_bt_cont) then
1113  do j=js,je ; do i=is-1,ie
1114  ubt(i,j) = uhbt_to_ubt(uhbt(i,j),btcl_u(i,j), guess=cs%ubt_IC(i,j))
1115  enddo ; enddo
1116  do j=js-1,je ; do i=is,ie
1117  vbt(i,j) = vhbt_to_vbt(vhbt(i,j),btcl_v(i,j), guess=cs%vbt_IC(i,j))
1118  enddo ; enddo
1119  else
1120  do j=js,je ; do i=is-1,ie
1121  ubt(i,j) = 0.0 ; if (datu(i,j) > 0.0) ubt(i,j) = uhbt(i,j) / datu(i,j)
1122  enddo ; enddo
1123  do j=js-1,je ; do i=is,ie
1124  vbt(i,j) = 0.0 ; if (datv(i,j) > 0.0) vbt(i,j) = vhbt(i,j) / datv(i,j)
1125  enddo ; enddo
1126  endif
1127  else
1128  do k=1,nz ; do j=js,je ; do i=is-1,ie
1129  ubt(i,j) = ubt(i,j) + wt_u(i,j,k) * u_in(i,j,k)
1130  enddo ; enddo ; enddo
1131  do k=1,nz ; do j=js-1,je ; do i=is,ie
1132  vbt(i,j) = vbt(i,j) + wt_v(i,j,k) * v_in(i,j,k)
1133  enddo ; enddo ; enddo
1134  endif
1135 
1136  if (cs%gradual_BT_ICs) then
1137  if (use_fluxes) then
1138  if (use_bt_cont) then
1139  do j=js,je ; do i=is-1,ie
1140  vel_tmp = uhbt_to_ubt(cs%uhbt_IC(i,j),btcl_u(i,j), guess=cs%ubt_IC(i,j))
1141  bt_force_u(i,j) = bt_force_u(i,j) + (ubt(i,j) - vel_tmp) * idt
1142  ubt(i,j) = vel_tmp
1143  enddo ; enddo
1144  do j=js-1,je ; do i=is,ie
1145  vel_tmp = vhbt_to_vbt(cs%vhbt_IC(i,j),btcl_v(i,j), guess=cs%vbt_IC(i,j))
1146  bt_force_v(i,j) = bt_force_v(i,j) + (vbt(i,j) - vel_tmp) * idt
1147  vbt(i,j) = vel_tmp
1148  enddo ; enddo
1149  else
1150  do j=js,je ; do i=is-1,ie
1151  vel_tmp = 0.0 ; if (datu(i,j) > 0.0) vel_tmp = cs%uhbt_IC(i,j) / datu(i,j)
1152  bt_force_u(i,j) = bt_force_u(i,j) + (ubt(i,j) - vel_tmp) * idt
1153  ubt(i,j) = vel_tmp
1154  enddo ; enddo
1155  do j=js-1,je ; do i=is,ie
1156  vel_tmp = 0.0 ; if (datv(i,j) > 0.0) vel_tmp = cs%vhbt_IC(i,j) / datv(i,j)
1157  bt_force_v(i,j) = bt_force_v(i,j) + (vbt(i,j) - vel_tmp) * idt
1158  vbt(i,j) = vel_tmp
1159  enddo ; enddo
1160  endif
1161  else
1162  do j=js,je ; do i=is-1,ie
1163  bt_force_u(i,j) = bt_force_u(i,j) + (ubt(i,j) - cs%ubt_IC(i,j)) * idt
1164  ubt(i,j) = cs%ubt_IC(i,j)
1165  enddo ; enddo
1166  do j=js-1,je ; do i=is,ie
1167  bt_force_v(i,j) = bt_force_v(i,j) + (vbt(i,j) - cs%vbt_IC(i,j)) * idt
1168  vbt(i,j) = cs%vbt_IC(i,j)
1169  enddo ; enddo
1170  endif
1171  endif
1172 
1173  if ((isq > is-1) .or. (jsq > js-1)) then
1174  ! Non-symmetric memory is being used, so the edge values need to be
1175  ! filled in with a halo update of a non-symmetric array.
1176  if (id_clock_calc_pre > 0) call cpu_clock_end(id_clock_calc_pre)
1177  if (id_clock_pass_pre > 0) call cpu_clock_begin(id_clock_pass_pre)
1178  tmp_u(:,:) = 0.0 ; tmp_v(:,:) = 0.0
1179  do j=js,je ; do i=isq,ieq ; tmp_u(i,j) = bt_force_u(i,j) ; enddo ; enddo
1180  do j=jsq,jeq ; do i=is,ie ; tmp_v(i,j) = bt_force_v(i,j) ; enddo ; enddo
1181  if (nonblock_setup) then
1182  pid_tmp_u = pass_vector_start(tmp_u, tmp_v, g%Domain)
1183  else
1184  call pass_vector(tmp_u, tmp_v, g%Domain, complete=.true.)
1185  do j=jsd,jed ; do i=isdb,iedb ; bt_force_u(i,j) = tmp_u(i,j) ; enddo ; enddo
1186  do j=jsdb,jedb ; do i=isd,ied ; bt_force_v(i,j) = tmp_v(i,j) ; enddo ; enddo
1187  endif
1188  if (id_clock_pass_pre > 0) call cpu_clock_end(id_clock_pass_pre)
1189  if (id_clock_calc_pre > 0) call cpu_clock_begin(id_clock_calc_pre)
1190  endif
1191 
1192  if (nonblock_setup) then
1193  if (id_clock_calc_pre > 0) call cpu_clock_end(id_clock_calc_pre)
1194  if (id_clock_pass_pre > 0) call cpu_clock_begin(id_clock_pass_pre)
1195  pid_gtot_e = pass_vector_start(gtot_e, gtot_n, cs%BT_Domain, &
1196  to_all+scalar_pair, agrid, complete=.false.)
1197  pid_gtot_w = pass_vector_start(gtot_w, gtot_s, cs%BT_Domain, &
1198  to_all+scalar_pair, agrid)
1199  if (id_clock_pass_pre > 0) call cpu_clock_end(id_clock_pass_pre)
1200  if (id_clock_calc_pre > 0) call cpu_clock_begin(id_clock_calc_pre)
1201  endif
1202 
1203  ! Determine the weighted Coriolis parameters for the neighboring velocities.
1204 !$OMP parallel do default(none) shared(isvf,ievf,jsvf,jevf,amer,bmer,cmer,dmer,DCor_u,q,CS)
1205  do j=jsvf-1,jevf ; do i=isvf-1,ievf+1
1206  if (cs%Sadourny) then
1207  amer(i-1,j) = dcor_u(i-1,j) * q(i-1,j)
1208  bmer(i,j) = dcor_u(i,j) * q(i,j)
1209  cmer(i,j+1) = dcor_u(i,j+1) * q(i,j)
1210  dmer(i-1,j+1) = dcor_u(i-1,j+1) * q(i-1,j)
1211  else
1212  amer(i-1,j) = dcor_u(i-1,j) * &
1213  ((q(i,j) + q(i-1,j-1)) + q(i-1,j)) / 3.0
1214  bmer(i,j) = dcor_u(i,j) * &
1215  (q(i,j) + (q(i-1,j) + q(i,j-1))) / 3.0
1216  cmer(i,j+1) = dcor_u(i,j+1) * &
1217  (q(i,j) + (q(i-1,j) + q(i,j+1))) / 3.0
1218  dmer(i-1,j+1) = dcor_u(i-1,j+1) * &
1219  ((q(i,j) + q(i-1,j+1)) + q(i-1,j)) / 3.0
1220  endif
1221  enddo ; enddo
1222 
1223 !$OMP parallel do default(none) shared(isvf,ievf,jsvf,jevf,azon,bzon,czon,dzon,DCor_v,q,CS)
1224  do j=jsvf-1,jevf+1 ; do i=isvf-1,ievf
1225  if (cs%Sadourny) then
1226  azon(i,j) = dcor_v(i+1,j) * q(i,j)
1227  bzon(i,j) = dcor_v(i,j) * q(i,j)
1228  czon(i,j) = dcor_v(i,j-1) * q(i,j-1)
1229  dzon(i,j) = dcor_v(i+1,j-1) * q(i,j-1)
1230  else
1231  azon(i,j) = dcor_v(i+1,j) * &
1232  (q(i,j) + (q(i+1,j) + q(i,j-1))) / 3.0
1233  bzon(i,j) = dcor_v(i,j) * &
1234  (q(i,j) + (q(i-1,j) + q(i,j-1))) / 3.0
1235  czon(i,j) = dcor_v(i,j-1) * &
1236  ((q(i,j) + q(i-1,j-1)) + q(i,j-1)) / 3.0
1237  dzon(i,j) = dcor_v(i+1,j-1) * &
1238  ((q(i,j) + q(i+1,j-1)) + q(i,j-1)) / 3.0
1239  endif
1240  enddo ; enddo
1241 
1242  ! If they are present, use u_Cor and v_Cor as the reference values for the
1243  ! Coriolis terms, including the viscous remnant if it is present.
1244  if (use_fluxes) then
1245  do j=js-1,je+1 ; do i=is-1,ie ; uhbt(i,j) = 0.0 ; enddo ; enddo
1246  do j=js-1,je ; do i=is-1,ie+1 ; vhbt(i,j) = 0.0 ; enddo ; enddo
1247  do k=1,nz ; do j=js-1,je+1 ; do i=is-1,ie
1248  uhbt(i,j) = uhbt(i,j) + u_cor(i,j,k)
1249  enddo ; enddo ; enddo
1250  do k=1,nz ; do j=js-1,je ; do i=is-1,ie+1
1251  vhbt(i,j) = vhbt(i,j) + v_cor(i,j,k)
1252  enddo ; enddo ; enddo
1253  if (use_bt_cont) then
1254  do j=js-1,je+1 ; do i=is-1,ie
1255  ubt_cor(i,j) = uhbt_to_ubt(uhbt(i,j), btcl_u(i,j), guess=cs%ubtav(i,j))
1256  enddo ; enddo
1257  do j=js-1,je ; do i=is-1,ie+1
1258  vbt_cor(i,j) = vhbt_to_vbt(vhbt(i,j), btcl_v(i,j), guess=cs%vbtav(i,j))
1259  enddo ; enddo
1260  else
1261  do j=js-1,je+1 ; do i=is-1,ie
1262  ubt_cor(i,j) = 0.0 ; if (datu(i,j)>0.0) ubt_cor(i,j) = uhbt(i,j)/datu(i,j)
1263  enddo ; enddo
1264  do j=js-1,je ; do i=is-1,ie+1
1265  vbt_cor(i,j) = 0.0 ; if (datv(i,j)>0.0) vbt_cor(i,j) = vhbt(i,j)/datv(i,j)
1266  enddo ; enddo
1267  endif
1268  else
1269  do j=js-1,je+1 ; do i=is-1,ie ; ubt_cor(i,j) = 0.0 ; enddo ; enddo
1270  do j=js-1,je ; do i=is-1,ie+1 ; vbt_cor(i,j) = 0.0 ; enddo ; enddo
1271  do k=1,nz ; do j=js-1,je+1 ; do i=is-1,ie
1272  ubt_cor(i,j) = ubt_cor(i,j) + wt_u(i,j,k) * u_cor(i,j,k)
1273  enddo ; enddo ; enddo
1274  do k=1,nz ; do j=js-1,je ; do i=is-1,ie+1
1275  vbt_cor(i,j) = vbt_cor(i,j) + wt_v(i,j,k) * v_cor(i,j,k)
1276  enddo ; enddo ; enddo
1277  endif
1278 
1279 !$OMP parallel do default(none) shared(is,ie,js,je,Cor_ref_u,azon,bzon,czon,dzon,vbt_Cor)
1280  do j=js,je ; do i=is-1,ie
1281  cor_ref_u(i,j) = &
1282  ((azon(i,j) * vbt_cor(i+1,j) + czon(i,j) * vbt_cor(i ,j-1)) + &
1283  (bzon(i,j) * vbt_cor(i ,j) + dzon(i,j) * vbt_cor(i+1,j-1)))
1284  enddo ; enddo
1285 !$OMP parallel do default(none) shared(is,ie,js,je,Cor_ref_v,amer,bmer,cmer,dmer,ubt_Cor)
1286  do j=js-1,je ; do i=is,ie
1287  cor_ref_v(i,j) = -1.0 * &
1288  ((amer(i-1,j) * ubt_cor(i-1,j) + cmer(i ,j+1) * ubt_cor(i ,j+1)) + &
1289  (bmer(i ,j) * ubt_cor(i ,j) + dmer(i-1,j+1) * ubt_cor(i-1,j+1)))
1290  enddo ; enddo
1291 
1292 ! Complete the previously initiated message passing.
1293  if (id_clock_calc_pre > 0) call cpu_clock_end(id_clock_calc_pre)
1294  if (id_clock_pass_pre > 0) call cpu_clock_begin(id_clock_pass_pre)
1295  if (nonblock_setup) then
1296  if ((isq > is-1) .or. (jsq > js-1)) then
1297  call pass_vector_complete(pid_tmp_u, tmp_u, tmp_v, g%Domain)
1298  do j=jsd,jed ; do i=isdb,iedb ; bt_force_u(i,j) = tmp_u(i,j) ; enddo ; enddo
1299  do j=jsdb,jedb ; do i=isd,ied ; bt_force_v(i,j) = tmp_v(i,j) ; enddo ; enddo
1300  endif
1301  call pass_vector_complete(pid_gtot_e, gtot_e, gtot_n, cs%BT_Domain, to_all+scalar_pair, agrid)
1302  call pass_vector_complete(pid_gtot_w, gtot_w, gtot_s, cs%BT_Domain, to_all+scalar_pair, agrid)
1303  else
1304  call pass_vector(gtot_e, gtot_n, cs%BT_Domain, to_all+scalar_pair, agrid, complete=.false.)
1305  call pass_vector(gtot_w, gtot_s, cs%BT_Domain, to_all+scalar_pair, agrid, complete=.true.)
1306  endif
1307  ! The various elements of gtot are positive definite but directional, so use
1308  ! the polarity arrays to sort out when the directions have shifted.
1309  do j=jsvf-1,jevf+1 ; do i=isvf-1,ievf+1
1310  if (cs%ua_polarity(i,j) < 0.0) call swap(gtot_e(i,j), gtot_w(i,j))
1311  if (cs%va_polarity(i,j) < 0.0) call swap(gtot_n(i,j), gtot_s(i,j))
1312  enddo ; enddo
1313 
1314  ! Now start new halo updates.
1315  if (nonblock_setup) then
1316  if (.not.use_bt_cont) &
1317  pid_datu = pass_vector_start(datu, datv, cs%BT_Domain, to_all+scalar_pair)
1318  ! The following halo update is not needed without wide halos. RWH
1319  if (((g%isd > cs%isdw) .or. (g%jsd > cs%jsdw)) .or. (isq <= is-1) .or. (jsq <= js-1)) &
1320  pid_bt_force_u = pass_vector_start(bt_force_u, bt_force_v, cs%BT_Domain, &
1321  complete=.false.)
1322  if (add_uh0) pid_uhbt0 = pass_vector_start(uhbt0, vhbt0, cs%BT_Domain)
1323  pid_cor_ref = pass_vector_start(cor_ref_u, cor_ref_v, cs%BT_Domain)
1324  endif
1325  if (id_clock_pass_pre > 0) call cpu_clock_end(id_clock_pass_pre)
1326  if (id_clock_calc_pre > 0) call cpu_clock_begin(id_clock_calc_pre)
1327 
1328  do j=js-1,je+1 ; do i=is-1,ie ; bt_rem_u(i,j) = g%mask2dCu(i,j) ; enddo ; enddo
1329  do j=js-1,je ; do i=is-1,ie+1 ; bt_rem_v(i,j) = g%mask2dCv(i,j) ; enddo ; enddo
1330  if ((use_visc_rem) .and. (cs%drag_amp > 0.0)) then
1331  do j=js-1,je+1 ; do i=is-1,ie ; av_rem_u(i,j) = 0.0 ; enddo ; enddo
1332  do j=js-1,je ; do i=is-1,ie+1 ; av_rem_v(i,j) = 0.0 ; enddo ; enddo
1333  do k=1,nz ; do j=js-1,je+1 ; do i=is-1,ie
1334  av_rem_u(i,j) = av_rem_u(i,j) + cs%frhatu(i,j,k) * visc_rem_u(i,j,k)
1335  enddo ; enddo ; enddo
1336  do k=1,nz ; do j=js-1,je ; do i=is-1,ie+1
1337  av_rem_v(i,j) = av_rem_v(i,j) + cs%frhatv(i,j,k) * visc_rem_v(i,j,k)
1338  enddo ; enddo ; enddo
1339  if (cs%strong_drag) then
1340  do j=js-1,je+1 ; do i=is-1,ie
1341  bt_rem_u(i,j) = g%mask2dCu(i,j) * cs%drag_amp * &
1342  ((nstep * av_rem_u(i,j)) / (1.0 + (nstep-1)*av_rem_u(i,j)))
1343  enddo ; enddo
1344  do j=js-1,je ; do i=is-1,ie+1
1345  bt_rem_v(i,j) = g%mask2dCv(i,j) * cs%drag_amp * &
1346  ((nstep * av_rem_v(i,j)) / (1.0 + (nstep-1)*av_rem_v(i,j)))
1347  enddo ; enddo
1348  else
1349  do j=js-1,je+1 ; do i=is-1,ie
1350  bt_rem_u(i,j) = 0.0
1351  if (g%mask2dCu(i,j) * av_rem_u(i,j) > 0.0) &
1352  bt_rem_u(i,j) = g%mask2dCu(i,j) * cs%drag_amp * (av_rem_u(i,j)**instep)
1353  enddo ; enddo
1354  do j=js-1,je ; do i=is-1,ie+1
1355  bt_rem_v(i,j) = 0.0
1356  if (g%mask2dCv(i,j) * av_rem_v(i,j) > 0.0) &
1357  bt_rem_v(i,j) = g%mask2dCv(i,j) * cs%drag_amp * (av_rem_v(i,j)**instep)
1358  enddo ; enddo
1359  endif
1360  endif
1361 
1362  ! Zero out the arrays for various time-averaged quantities.
1363  if (find_etaav) then ; do j=jsvf-1,jevf+1 ; do i=isvf-1,ievf+1
1364  eta_sum(i,j) = 0.0 ; eta_wtd(i,j) = 0.0
1365  enddo ; enddo ; else ; do j=jsvf-1,jevf+1 ; do i=isvf-1,ievf+1
1366  eta_wtd(i,j) = 0.0
1367  enddo ; enddo ; endif
1368  do j=jsvf-1,jevf+1 ; do i=isvf-1,ievf
1369  ubt_sum(i,j) = 0.0 ; uhbt_sum(i,j) = 0.0
1370  pfu_bt_sum(i,j) = 0.0 ; coru_bt_sum(i,j) = 0.0
1371  ubt_wtd(i,j) = 0.0 ; ubt_trans(i,j) = 0.0
1372  enddo ; enddo
1373  do j=jsvf-1,jevf ; do i=isvf-1,ievf+1
1374  vbt_sum(i,j) = 0.0 ; vhbt_sum(i,j) = 0.0
1375  pfv_bt_sum(i,j) = 0.0 ; corv_bt_sum(i,j) = 0.0
1376  vbt_wtd(i,j) = 0.0 ; vbt_trans(i,j) = 0.0
1377  enddo ; enddo
1378 
1379  ! Set the mass source, after first initializing the halos to 0.
1380  do j=jsvf-1,jevf+1; do i=isvf-1,ievf+1 ; eta_src(i,j) = 0.0 ; enddo ; enddo
1381  if (cs%bound_BT_corr) then ; do j=js,je ; do i=is,ie
1382  if (abs(cs%eta_cor(i,j)) > dt*cs%eta_cor_bound(i,j)) &
1383  cs%eta_cor(i,j) = sign(dt*cs%eta_cor_bound(i,j),cs%eta_cor(i,j))
1384  enddo ; enddo ; endif
1385  do j=js,je ; do i=is,ie
1386  eta_src(i,j) = g%mask2dT(i,j) * (instep * cs%eta_cor(i,j) + dtbt * cs%eta_source(i,j))
1387  enddo ; enddo
1388 
1389  if (cs%dynamic_psurf) then
1390  ice_is_rigid = (associated(fluxes%rigidity_ice_u) .and. &
1391  associated(fluxes%rigidity_ice_v))
1392  h_min_dyn = gv%m_to_H * cs%Dmin_dyn_psurf
1393  if (ice_is_rigid .and. use_bt_cont) &
1394  call bt_cont_to_face_areas(bt_cont, datu, datv, g, ms, 0, .true.)
1395  if (ice_is_rigid) then ; do j=js,je ; do i=is,ie
1396  ! First determine the maximum stable value for dyn_coef_eta.
1397 
1398  ! This estimate of the maximum stable time step is pretty accurate for
1399  ! gravity waves, but it is a conservative estimate since it ignores the
1400  ! stabilizing effect of the bottom drag.
1401  idt_max2 = 0.5 * (dgeo_de * (1.0 + 2.0*bebt)) * (g%IareaT(i,j) * &
1402  ((gtot_e(i,j) * (datu(i,j)*g%IdxCu(i,j)) + &
1403  gtot_w(i,j) * (datu(i-1,j)*g%IdxCu(i-1,j))) + &
1404  (gtot_n(i,j) * (datv(i,j)*g%IdyCv(i,j)) + &
1405  gtot_s(i,j) * (datv(i,j-1)*g%IdyCv(i,j-1)))) + &
1406  ((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
1407  (g%CoriolisBu(i-1,j)**2 + g%CoriolisBu(i,j-1)**2)))
1408  h_eff_dx2 = max(h_min_dyn * (g%IdxT(i,j)**2 + g%IdyT(i,j)**2), &
1409  g%IareaT(i,j) * &
1410  ((datu(i,j)*g%IdxCu(i,j) + datu(i-1,j)*g%IdxCu(i-1,j)) + &
1411  (datv(i,j)*g%IdyCv(i,j) + datv(i,j-1)*g%IdyCv(i,j-1)) ) )
1412  dyn_coef_max = cs%const_dyn_psurf * max(0.0, 1.0 - dtbt**2 * idt_max2) / &
1413  (dtbt**2 * h_eff_dx2)
1414 
1415  ! ice_strength has units of m s-2. rigidity_ice_[uv] has units of m3 s-1.
1416  ice_strength = ((fluxes%rigidity_ice_u(i,j) + fluxes%rigidity_ice_u(i-1,j)) + &
1417  (fluxes%rigidity_ice_v(i,j) + fluxes%rigidity_ice_v(i,j-1))) / &
1418  (cs%ice_strength_length**2 * dtbt)
1419 
1420  ! Units of dyn_coef: m2 s-2 H-1
1421  dyn_coef_eta(i,j) = min(dyn_coef_max, ice_strength * gv%H_to_m)
1422  enddo ; enddo ; endif
1423  endif
1424 
1425  if (id_clock_calc_pre > 0) call cpu_clock_end(id_clock_calc_pre)
1426  if (id_clock_pass_pre > 0) call cpu_clock_begin(id_clock_pass_pre)
1427  if (nonblock_setup) then
1428  if (cs%dynamic_psurf) pid_dyn_coef_eta = &
1429  pass_var_start(dyn_coef_eta, cs%BT_Domain, complete=.false.)
1430  if (interp_eta_pf) then
1431  pid_eta_pf_1 = pass_var_start(eta_pf_1, cs%BT_Domain, complete=.false.)
1432  pid_d_eta_pf = pass_var_start(d_eta_pf, cs%BT_Domain, complete=.false.)
1433  else
1434  if ((g%isd > cs%isdw) .or. (g%jsd > cs%jsdw)) &
1435  pid_eta_pf = pass_var_start(eta_pf, cs%BT_Domain, complete=.false.)
1436  endif
1437  pid_eta_src = pass_var_start(eta_src, cs%BT_Domain)
1438 
1439  ! The following halo update is not needed without wide halos. RWH
1440  if (ievf > ie) &
1441  pid_bt_rem_u = pass_vector_start(bt_rem_u, bt_rem_v, cs%BT_Domain, &
1442  to_all+scalar_pair)
1443  else
1444  if (interp_eta_pf) then
1445  call pass_var(eta_pf_1, cs%BT_Domain, complete=.false.)
1446  call pass_var(d_eta_pf, cs%BT_Domain, complete=.false.)
1447  else
1448  ! eta_PF_in had correct values in its halos, so only update eta_PF with
1449  ! extra-wide halo arrays. This could have started almost immediately.
1450  if ((g%isd > cs%isdw) .or. (g%jsd > cs%jsdw)) &
1451  call pass_var(eta_pf, cs%BT_Domain, complete=.false.)
1452  endif
1453  if (cs%dynamic_psurf) call pass_var(dyn_coef_eta, cs%BT_Domain, complete=.false.)
1454  ! The following halo update is not needed without wide halos. RWH
1455  if (ievf > ie) &
1456  call pass_vector(bt_rem_u, bt_rem_v, cs%BT_Domain, to_all+scalar_pair)
1457  if (.not.use_bt_cont) &
1458  call pass_vector(datu, datv, cs%BT_Domain, to_all+scalar_pair)
1459  if (((g%isd > cs%isdw) .or. (g%jsd > cs%jsdw)) .or. (isq <= is-1) .or. (jsq <= js-1)) &
1460  call pass_vector(bt_force_u, bt_force_v, cs%BT_Domain, complete=.false.)
1461  if (g%nonblocking_updates) then ! Passing needs to be completed now.
1462  call pass_var(eta_src, cs%BT_Domain, complete=.true.)
1463  if (add_uh0) call pass_vector(uhbt0, vhbt0, cs%BT_Domain, complete=.false.)
1464  call pass_vector(cor_ref_u, cor_ref_v, cs%BT_Domain, complete=.true.)
1465  else
1466  call pass_var(eta_src, cs%BT_Domain, complete=.false.)
1467  if (add_uh0) call pass_vector(uhbt0, vhbt0, cs%BT_Domain, complete=.false.)
1468  call pass_vector(cor_ref_u, cor_ref_v, cs%BT_Domain, complete=.false.)
1469  endif
1470  endif
1471  if (id_clock_pass_pre > 0) call cpu_clock_end(id_clock_pass_pre)
1472  if (id_clock_calc_pre > 0) call cpu_clock_begin(id_clock_calc_pre)
1473 
1474  ! Complete all of the outstanding halo updates.
1475  if (nonblock_setup) then
1476  if (id_clock_calc_pre > 0) call cpu_clock_end(id_clock_calc_pre)
1477  if (id_clock_pass_pre > 0) call cpu_clock_begin(id_clock_pass_pre)
1478 
1479  if (.not.use_bt_cont) & !### IS THIS OK HERE?
1480  call pass_vector_complete(pid_datu, datu, datv, cs%BT_Domain, to_all+scalar_pair)
1481  ! The following halo update is not needed without wide halos. RWH
1482  if (((g%isd > cs%isdw) .or. (g%jsd > cs%jsdw)) .or. (isq <= is-1) .or. (jsq <= js-1)) &
1483  call pass_vector_complete(pid_bt_force_u, bt_force_u, bt_force_v, cs%BT_Domain)
1484  if (add_uh0) call pass_vector_complete(pid_uhbt0, uhbt0, vhbt0, cs%BT_Domain)
1485  call pass_vector_complete(pid_cor_ref, cor_ref_u, cor_ref_v, cs%BT_Domain)
1486 
1487  if (cs%dynamic_psurf) &
1488  call pass_var_complete(pid_dyn_coef_eta, dyn_coef_eta, cs%BT_Domain)
1489  if (interp_eta_pf) then
1490  call pass_var_complete(pid_eta_pf_1, eta_pf_1, cs%BT_Domain)
1491  call pass_var_complete(pid_d_eta_pf, d_eta_pf, cs%BT_Domain)
1492  else
1493  if ((g%isd > cs%isdw) .or. (g%jsd > cs%jsdw)) &
1494  call pass_var_complete(pid_eta_pf, eta_pf, cs%BT_Domain)
1495  endif
1496  call pass_var_complete(pid_eta_src, eta_src, cs%BT_Domain)
1497 
1498  if (ievf > ie) &
1499  call pass_vector_complete(pid_bt_rem_u, bt_rem_u, bt_rem_v, cs%BT_Domain,&
1500  to_all+scalar_pair)
1501 
1502  if (id_clock_pass_pre > 0) call cpu_clock_end(id_clock_pass_pre)
1503  if (id_clock_calc_pre > 0) call cpu_clock_begin(id_clock_calc_pre)
1504  endif
1505 
1506  if (cs%debug) then
1507  call uvchksum("BT [uv]hbt", uhbt, vhbt, cs%debug_BT_HI, haloshift=0)
1508  call uvchksum("BT Initial [uv]bt", ubt, vbt, cs%debug_BT_HI, haloshift=0)
1509  call hchksum(eta, "BT Initial eta",cs%debug_BT_HI, haloshift=0, scale=gv%H_to_m)
1510  call uvchksum("BT BT_force_[uv]", &
1511  bt_force_u, bt_force_v, cs%debug_BT_HI, haloshift=0)
1512  if (interp_eta_pf) then
1513  call hchksum(eta_pf_1, "BT eta_PF_1",cs%debug_BT_HI,haloshift=0, scale=gv%H_to_m)
1514  call hchksum(d_eta_pf, "BT d_eta_PF",cs%debug_BT_HI,haloshift=0, scale=gv%H_to_m)
1515  else
1516  call hchksum(eta_pf, "BT eta_PF",cs%debug_BT_HI,haloshift=0, scale=gv%H_to_m)
1517  call hchksum(eta_pf_in, "BT eta_PF_in",g%HI,haloshift=0, scale=gv%H_to_m)
1518  endif
1519  call uvchksum("BT Cor_ref_[uv]", cor_ref_u, cor_ref_v, &
1520  cs%debug_BT_HI, haloshift=0)
1521  call uvchksum("BT [uv]hbt0", uhbt0, vhbt0, cs%debug_BT_HI, haloshift=0, scale=gv%H_to_m)
1522  if (.not. use_bt_cont) then
1523  call uvchksum("BT Dat[uv]", datu, datv, &
1524  cs%debug_BT_HI,haloshift=1, scale=gv%H_to_m)
1525  endif
1526  call uvchksum("BT wt_[uv]", wt_u, wt_v, g%HI,haloshift=1)
1527  call uvchksum("BT frhat[uv]", cs%frhatu, cs%frhatv, g%HI, haloshift=1)
1528  call uvchksum("BT bc_accel_[uv]", bc_accel_u, bc_accel_v, g%HI,haloshift=0)
1529  call uvchksum("BT IDat[uv]", cs%IDatu, cs%IDatv, g%HI,haloshift=0)
1530  if (use_visc_rem) then
1531  call uvchksum("BT visc_rem_[uv]", visc_rem_u, visc_rem_v, g%HI, haloshift=1)
1532  endif
1533  endif
1534 
1535  if (query_averaging_enabled(cs%diag)) then
1536  if (cs%id_eta_st > 0) call post_data(cs%id_eta_st, eta(isd:ied,jsd:jed), cs%diag)
1537  if (cs%id_ubt_st > 0) call post_data(cs%id_ubt_st, ubt(isdb:iedb,jsd:jed), cs%diag)
1538  if (cs%id_vbt_st > 0) call post_data(cs%id_vbt_st, vbt(isd:ied,jsdb:jedb), cs%diag)
1539  endif
1540 
1541  if (id_clock_calc_pre > 0) call cpu_clock_end(id_clock_calc_pre)
1542  if (id_clock_calc > 0) call cpu_clock_begin(id_clock_calc)
1543 
1544  if (project_velocity) then ; eta_pf_bt => eta ; else ; eta_pf_bt => eta_pred ; endif
1545 
1546  if (cs%dt_bt_filter >= 0.0) then
1547  dt_filt = 0.5 * max(0.0, min(cs%dt_bt_filter, 2.0*dt))
1548  else
1549  dt_filt = 0.5 * max(0.0, dt * min(-cs%dt_bt_filter, 2.0))
1550  endif
1551  nfilter = ceiling(dt_filt / dtbt)
1552 
1553  ! Set up the normalized weights for the filtered velocity.
1554  sum_wt_vel = 0.0 ; sum_wt_eta = 0.0 ; sum_wt_accel = 0.0 ; sum_wt_trans = 0.0
1555  allocate(wt_vel(nstep+nfilter)) ; allocate(wt_eta(nstep+nfilter))
1556  allocate(wt_trans(nstep+nfilter+1)) ; allocate(wt_accel(nstep+nfilter+1))
1557  allocate(wt_accel2(nstep+nfilter+1))
1558  do n=1,nstep+nfilter
1559  ! Modify this to use a different filter...
1560  if ( (n==nstep) .or. (dt_filt - abs(n-nstep)*dtbt >= 0.0)) then
1561  wt_vel(n) = 1.0 ; wt_eta(n) = 1.0
1562  elseif (dtbt + dt_filt - abs(n-nstep)*dtbt > 0.0) then
1563  wt_vel(n) = 1.0 + (dt_filt / dtbt) - abs(n-nstep) ; wt_eta(n) = wt_vel(n)
1564  else
1565  wt_vel(n) = 0.0 ; wt_eta(n) = 0.0
1566  endif
1567 !### if (n < nstep-nfilter) then ; wt_vel(n) = 0.0 ; else ; wt_vel(n) = 1.0 ; endif
1568 !### if (n < nstep-nfilter) then ; wt_eta(n) = 0.0 ; else ; wt_eta(n) = 1.0 ; endif
1569 
1570  ! The rest should not be changed.
1571  sum_wt_vel = sum_wt_vel + wt_vel(n) ; sum_wt_eta = sum_wt_eta + wt_eta(n)
1572  enddo
1573  wt_trans(nstep+nfilter+1) = 0.0 ; wt_accel(nstep+nfilter+1) = 0.0
1574  do n=nstep+nfilter,1,-1
1575  wt_trans(n) = wt_trans(n+1) + wt_eta(n)
1576  wt_accel(n) = wt_accel(n+1) + wt_vel(n)
1577  sum_wt_accel = sum_wt_accel + wt_accel(n) ; sum_wt_trans = sum_wt_trans + wt_trans(n)
1578  enddo
1579  ! Normalize the weights.
1580  i_sum_wt_vel = 1.0 / sum_wt_vel ; i_sum_wt_accel = 1.0 / sum_wt_accel
1581  i_sum_wt_eta = 1.0 / sum_wt_eta ; i_sum_wt_trans = 1.0 / sum_wt_trans
1582  do n=1,nstep+nfilter
1583  wt_vel(n) = wt_vel(n) * i_sum_wt_vel
1584  wt_accel2(n) = wt_accel(n)
1585  wt_accel(n) = wt_accel(n) * i_sum_wt_accel
1586  wt_eta(n) = wt_eta(n) * i_sum_wt_eta
1587 ! wt_trans(n) = wt_trans(n) * I_sum_wt_trans
1588  enddo
1589 
1590 
1591  sum_wt_vel = 0.0 ; sum_wt_eta = 0.0 ; sum_wt_accel = 0.0 ; sum_wt_trans = 0.0
1592 
1593  ! The following loop contains all of the time steps.
1594  isv=is ; iev=ie ; jsv=js ; jev=je
1595  do n=1,nstep+nfilter
1596 
1597  sum_wt_vel = sum_wt_vel + wt_vel(n)
1598  sum_wt_eta = sum_wt_eta + wt_eta(n)
1599  sum_wt_accel = sum_wt_accel + wt_accel2(n)
1600  sum_wt_trans = sum_wt_trans + wt_trans(n)
1601 
1602  if (cs%clip_velocity) then
1603  do j=jsv,jev ; do i=isv-1,iev
1604  if (abs(ubt(i,j)) > cs%maxvel) then
1605  ! Add some error handling later.
1606  ubt(i,j) = sign(cs%maxvel,ubt(i,j))
1607  endif
1608  enddo ; enddo
1609  do j=jsv-1,jev ; do i=isv,iev
1610  if (abs(vbt(i,j)) > cs%maxvel) then
1611  ! Add some error handling later.
1612  vbt(i,j) = sign(cs%maxvel,vbt(i,j))
1613  endif
1614  enddo ; enddo
1615  endif
1616 
1617  if ((iev - stencil < ie) .or. (jev - stencil < je)) then
1618  if (id_clock_calc > 0) call cpu_clock_end(id_clock_calc)
1619  if (id_clock_pass_step > 0) call cpu_clock_begin(id_clock_pass_step)
1620  if (g%nonblocking_updates) then
1621  pid_ubt = pass_vector_start(ubt, vbt, cs%BT_Domain)
1622  pid_eta = pass_var_start(eta, cs%BT_Domain)
1623  call pass_vector_complete(pid_ubt, ubt, vbt, cs%BT_Domain)
1624  call pass_var_complete(pid_eta, eta, cs%BT_Domain)
1625  else
1626  call pass_var(eta, cs%BT_Domain)
1627  call pass_vector(ubt, vbt, cs%BT_Domain)
1628  endif
1629  isv = isvf ; iev = ievf ; jsv = jsvf ; jev = jevf
1630  if (id_clock_pass_step > 0) call cpu_clock_end(id_clock_pass_step)
1631  if (id_clock_calc > 0) call cpu_clock_begin(id_clock_calc)
1632  else
1633  isv = isv+stencil ; iev = iev-stencil
1634  jsv = jsv+stencil ; jev = jev-stencil
1635  endif
1636 
1637  if ((.not.use_bt_cont) .and. cs%Nonlinear_continuity .and. &
1638  (cs%Nonlin_cont_update_period > 0)) then
1639  if ((n>1) .and. (mod(n-1,cs%Nonlin_cont_update_period) == 0)) &
1640  call find_face_areas(datu, datv, g, gv, cs, ms, cs%rescale_D_bt, eta, 1+iev-ie)
1641  endif
1642 
1643  if (cs%dynamic_psurf .or. .not.project_velocity) then
1644  if (use_bt_cont) then
1645 !$OMP parallel do default(none) shared(isv,iev,jsv,jev,uhbt,ubt,BTCL_u,uhbt0)
1646  do j=jsv-1,jev+1 ; do i=isv-2,iev+1
1647  uhbt(i,j) = find_uhbt(ubt(i,j),btcl_u(i,j)) + uhbt0(i,j)
1648  enddo ; enddo
1649  do j=jsv-2,jev+1 ; do i=isv-1,iev+1
1650  vhbt(i,j) = find_vhbt(vbt(i,j),btcl_v(i,j)) + vhbt0(i,j)
1651  enddo ; enddo
1652  do j=jsv-1,jev+1 ; do i=isv-1,iev+1
1653  eta_pred(i,j) = (eta(i,j) + eta_src(i,j)) + (dtbt * cs%IareaT(i,j)) * &
1654  ((uhbt(i-1,j) - uhbt(i,j)) + (vhbt(i,j-1) - vhbt(i,j)))
1655  enddo ; enddo
1656  else
1657 !$OMP parallel do default(none) shared(isv,iev,jsv,jev,eta_pred,eta,eta_src,dtbt,&
1658 !$OMP CS,Datu,ubt,uhbt0,Datv,vhbt0,vbt)
1659  do j=jsv-1,jev+1 ; do i=isv-1,iev+1
1660  eta_pred(i,j) = (eta(i,j) + eta_src(i,j)) + (dtbt * cs%IareaT(i,j)) * &
1661  (((datu(i-1,j)*ubt(i-1,j) + uhbt0(i-1,j)) - &
1662  (datu(i,j)*ubt(i,j) + uhbt0(i,j))) + &
1663  ((datv(i,j-1)*vbt(i,j-1) + vhbt0(i,j-1)) - &
1664  (datv(i,j)*vbt(i,j) + vhbt0(i,j))))
1665  enddo ; enddo
1666  endif
1667 
1668  if (cs%dynamic_psurf) then ; do j=jsv-1,jev+1 ; do i=isv-1,iev+1
1669  p_surf_dyn(i,j) = dyn_coef_eta(i,j) * (eta_pred(i,j) - eta(i,j))
1670  enddo ; enddo ; endif
1671  endif
1672 
1673  ! Recall that just outside the do n loop, there is code like...
1674  ! eta_PF_BT => eta_pred ; if (project_velocity) eta_PF_BT => eta
1675 
1676  if (find_etaav) then ; do j=js,je ; do i=is,ie
1677  eta_sum(i,j) = eta_sum(i,j) + wt_accel2(n) * eta_pf_bt(i,j)
1678  enddo ; enddo ; endif
1679 
1680  if (interp_eta_pf) then
1681  wt_end = n*instep ! This could be (n-0.5)*Instep.
1682  do j=jsv-1,jev+1 ; do i=isv-1,iev+1
1683  eta_pf(i,j) = eta_pf_1(i,j) + wt_end*d_eta_pf(i,j)
1684  enddo ; enddo
1685  endif
1686 
1687  if (apply_obc_flather) then
1688 !$OMP parallel do default(none) shared(isv,iev,jsv,jev,ubt_old,ubt)
1689  do j=jsv,jev ; do i=isv-2,iev+1
1690  ubt_old(i,j) = ubt(i,j)
1691  enddo; enddo
1692 !$OMP parallel do default(none) shared(isv,iev,jsv,jev,vbt_old,vbt)
1693  do j=jsv-2,jev+1 ; do i=isv,iev
1694  vbt_old(i,j) = vbt(i,j)
1695  enddo ; enddo
1696  endif
1697 
1698 !$OMP parallel default(none) shared(isv,iev,jsv,jev,G,amer,ubt,cmer,bmer,dmer,eta_PF_BT, &
1699 !$OMP eta_PF,gtot_N,gtot_S,dgeo_de,CS,p_surf_dyn,n, &
1700 !$OMP v_accel_bt,wt_accel,PFv_bt_sum,wt_accel2, &
1701 !$OMP Corv_bt_sum,BT_OBC,vbt,bt_rem_v,BT_force_v,vhbt, &
1702 !$OMP Cor_ref_v,find_PF,find_Cor,apply_v_OBCs,dtbt, &
1703 !$OMP project_velocity,be_proj,bebt,use_BT_cont,BTCL_v, &
1704 !$OMP vhbt0,Datv,vbt_sum,wt_trans,vhbt_sum,vbt_wtd,wt_vel, &
1705 !$OMP azon,bzon,czon,dzon,Cor_ref_u,gtot_E,gtot_W,OBC, &
1706 !$OMP u_accel_bt,PFu_bt_sum,Coru_bt_sum,apply_u_OBCs, &
1707 !$OMP bt_rem_u,BT_force_u,uhbt,BTCL_u,uhbt0,Datu,ubt_sum, &
1708 !$OMP uhbt_sum,ubt_wtd) &
1709 !$OMP private(Cor, gradP, vel_prev, vel_trans )
1710  if (mod(n+g%first_direction,2)==1) then
1711  ! On odd-steps, update v first.
1712 !$OMP do
1713  do j=jsv-1,jev ; do i=isv-1,iev+1
1714  cor = -1.0*((amer(i-1,j) * ubt(i-1,j) + cmer(i,j+1) * ubt(i,j+1)) + &
1715  (bmer(i,j) * ubt(i,j) + dmer(i-1,j+1) * ubt(i-1,j+1))) - cor_ref_v(i,j)
1716  gradp = ((eta_pf_bt(i,j)-eta_pf(i,j))*gtot_n(i,j) - &
1717  (eta_pf_bt(i,j+1)-eta_pf(i,j+1))*gtot_s(i,j+1)) * &
1718  dgeo_de * cs%IdyCv(i,j)
1719  if (cs%dynamic_psurf) &
1720  gradp = gradp + (p_surf_dyn(i,j) - p_surf_dyn(i,j+1)) * cs%IdyCv(i,j)
1721  v_accel_bt(i,j) = v_accel_bt(i,j) + wt_accel(n) * (cor + gradp)
1722  if (find_pf) pfv_bt_sum(i,j) = pfv_bt_sum(i,j) + wt_accel2(n) * gradp
1723  if (find_cor) corv_bt_sum(i,j) = corv_bt_sum(i,j) + wt_accel2(n) * cor
1724 
1725  if (apply_v_obcs) then ; if (obc%segnum_v(i,j) /= obc_none) cycle ; endif
1726 
1727  vel_prev = vbt(i,j)
1728  vbt(i,j) = bt_rem_v(i,j) * (vbt(i,j) + &
1729  dtbt * ((bt_force_v(i,j) + cor) + gradp))
1730  if (project_velocity) then
1731  vel_trans = (1.0 + be_proj)*vbt(i,j) - be_proj*vel_prev
1732  else
1733  vel_trans = (1.0-bebt)*vel_prev + bebt*vbt(i,j)
1734  endif
1735  if (use_bt_cont) then
1736  vhbt(i,j) = find_vhbt(vel_trans,btcl_v(i,j)) + vhbt0(i,j)
1737  else
1738  vhbt(i,j) = datv(i,j)*vel_trans + vhbt0(i,j)
1739  endif
1740 
1741  vbt_sum(i,j) = vbt_sum(i,j) + wt_trans(n) * vel_trans
1742  vhbt_sum(i,j) = vhbt_sum(i,j) + wt_trans(n) * vhbt(i,j)
1743  vbt_wtd(i,j) = vbt_wtd(i,j) + wt_vel(n) * vbt(i,j)
1744  enddo ; enddo
1745 
1746 !$OMP do
1747  do j=jsv,jev ; do i=isv-1,iev
1748  cor = ((azon(i,j) * vbt(i+1,j) + czon(i,j) * vbt(i,j-1)) + &
1749  (bzon(i,j) * vbt(i,j) + dzon(i,j) * vbt(i+1,j-1))) - cor_ref_u(i,j)
1750  gradp = ((eta_pf_bt(i,j)-eta_pf(i,j))*gtot_e(i,j) - &
1751  (eta_pf_bt(i+1,j)-eta_pf(i+1,j))*gtot_w(i+1,j)) * &
1752  dgeo_de * cs%IdxCu(i,j)
1753  if (cs%dynamic_psurf) &
1754  gradp = gradp + (p_surf_dyn(i,j) - p_surf_dyn(i+1,j)) * cs%IdxCu(i,j)
1755  u_accel_bt(i,j) = u_accel_bt(i,j) + wt_accel(n) * (cor + gradp)
1756  if (find_pf) pfu_bt_sum(i,j) = pfu_bt_sum(i,j) + wt_accel2(n) * gradp
1757  if (find_cor) coru_bt_sum(i,j) = coru_bt_sum(i,j) + wt_accel2(n) * cor
1758 
1759  if (apply_u_obcs) then ; if (obc%segnum_u(i,j) /= obc_none) cycle ; endif
1760 
1761  vel_prev = ubt(i,j)
1762  ubt(i,j) = bt_rem_u(i,j) * (ubt(i,j) + &
1763  dtbt * ((bt_force_u(i,j) + cor) + gradp))
1764  if (project_velocity) then
1765  vel_trans = (1.0 + be_proj)*ubt(i,j) - be_proj*vel_prev
1766  else
1767  vel_trans = (1.0-bebt)*vel_prev + bebt*ubt(i,j)
1768  endif
1769  if (use_bt_cont) then
1770  uhbt(i,j) = find_uhbt(vel_trans, btcl_u(i,j)) + uhbt0(i,j)
1771  else
1772  uhbt(i,j) = datu(i,j)*vel_trans + uhbt0(i,j)
1773  endif
1774 
1775  ubt_sum(i,j) = ubt_sum(i,j) + wt_trans(n) * vel_trans
1776  uhbt_sum(i,j) = uhbt_sum(i,j) + wt_trans(n) * uhbt(i,j)
1777  ubt_wtd(i,j) = ubt_wtd(i,j) + wt_vel(n) * ubt(i,j)
1778  enddo ; enddo
1779 
1780  else
1781  ! On even steps, update u first.
1782 !$OMP do
1783  do j=jsv-1,jev+1 ; do i=isv-1,iev
1784  cor = ((azon(i,j) * vbt(i+1,j) + czon(i,j) * vbt(i,j-1)) + &
1785  (bzon(i,j) * vbt(i,j) + dzon(i,j) * vbt(i+1,j-1))) - cor_ref_u(i,j)
1786  gradp = ((eta_pf_bt(i,j)-eta_pf(i,j))*gtot_e(i,j) - &
1787  (eta_pf_bt(i+1,j)-eta_pf(i+1,j))*gtot_w(i+1,j)) * &
1788  dgeo_de * cs%IdxCu(i,j)
1789  if (cs%dynamic_psurf) &
1790  gradp = gradp + (p_surf_dyn(i,j) - p_surf_dyn(i+1,j)) * cs%IdxCu(i,j)
1791  u_accel_bt(i,j) = u_accel_bt(i,j) + wt_accel(n) * (cor + gradp)
1792  if (find_pf) pfu_bt_sum(i,j) = pfu_bt_sum(i,j) + wt_accel2(n) * gradp
1793  if (find_cor) coru_bt_sum(i,j) = coru_bt_sum(i,j) + wt_accel2(n) * cor
1794 
1795  if (apply_u_obcs) then ; if (obc%segnum_u(i,j) /= obc_none) cycle ; endif
1796 
1797  vel_prev = ubt(i,j)
1798  ubt(i,j) = bt_rem_u(i,j) * (ubt(i,j) + &
1799  dtbt * ((bt_force_u(i,j) + cor) + gradp))
1800  if (project_velocity) then
1801  vel_trans = (1.0 + be_proj)*ubt(i,j) - be_proj*vel_prev
1802  else
1803  vel_trans = (1.0-bebt)*vel_prev + bebt*ubt(i,j)
1804  endif
1805  if (use_bt_cont) then
1806  uhbt(i,j) = find_uhbt(vel_trans,btcl_u(i,j)) + uhbt0(i,j)
1807  else
1808  uhbt(i,j) = datu(i,j)*vel_trans + uhbt0(i,j)
1809  endif
1810 
1811  ubt_sum(i,j) = ubt_sum(i,j) + wt_trans(n) * vel_trans
1812  uhbt_sum(i,j) = uhbt_sum(i,j) + wt_trans(n) * uhbt(i,j)
1813  ubt_wtd(i,j) = ubt_wtd(i,j) + wt_vel(n) * ubt(i,j)
1814  enddo ; enddo
1815 
1816 !$OMP do
1817  do j=jsv-1,jev ; do i=isv,iev
1818  cor = -1.0*((amer(i-1,j) * ubt(i-1,j) + bmer(i,j) * ubt(i,j)) + &
1819  (cmer(i,j+1) * ubt(i,j+1) + dmer(i-1,j+1) * ubt(i-1,j+1))) - cor_ref_v(i,j)
1820  gradp = ((eta_pf_bt(i,j)-eta_pf(i,j))*gtot_n(i,j) - &
1821  (eta_pf_bt(i,j+1)-eta_pf(i,j+1))*gtot_s(i,j+1)) * &
1822  dgeo_de * cs%IdyCv(i,j)
1823  if (cs%dynamic_psurf) &
1824  gradp = gradp + (p_surf_dyn(i,j) - p_surf_dyn(i,j+1)) * cs%IdyCv(i,j)
1825  v_accel_bt(i,j) = v_accel_bt(i,j) + wt_accel(n) * (cor + gradp)
1826  if (find_pf) pfv_bt_sum(i,j) = pfv_bt_sum(i,j) + wt_accel2(n) * gradp
1827  if (find_cor) corv_bt_sum(i,j) = corv_bt_sum(i,j) + wt_accel2(n) * cor
1828 
1829  if (apply_v_obcs) then ; if (obc%segnum_v(i,j) /= obc_none) cycle ; endif
1830 
1831  vel_prev = vbt(i,j)
1832  vbt(i,j) = bt_rem_v(i,j) * (vbt(i,j) + &
1833  dtbt * ((bt_force_v(i,j) + cor) + gradp))
1834  if (project_velocity) then
1835  vel_trans = (1.0 + be_proj)*vbt(i,j) - be_proj*vel_prev
1836  else
1837  vel_trans = (1.0-bebt)*vel_prev + bebt*vbt(i,j)
1838  endif
1839  if (use_bt_cont) then
1840  vhbt(i,j) = find_vhbt(vel_trans,btcl_v(i,j)) + vhbt0(i,j)
1841  else
1842  vhbt(i,j) = datv(i,j)*vel_trans + vhbt0(i,j)
1843  endif
1844 
1845  vbt_sum(i,j) = vbt_sum(i,j) + wt_trans(n) * vel_trans
1846  vhbt_sum(i,j) = vhbt_sum(i,j) + wt_trans(n) * vhbt(i,j)
1847  vbt_wtd(i,j) = vbt_wtd(i,j) + wt_vel(n) * vbt(i,j)
1848  enddo ; enddo
1849  endif
1850 !$OMP end parallel
1851 
1852  if (apply_obcs) then
1853  call apply_velocity_obcs(obc, ubt, vbt, uhbt, vhbt, &
1854  ubt_trans, vbt_trans, eta, ubt_old, vbt_old, bt_obc, &
1855  g, ms, iev-ie, dtbt, bebt, use_bt_cont, datu, datv, btcl_u, btcl_v, &
1856  uhbt0, vhbt0)
1857  if (apply_u_obcs) then ; do j=js,je ; do i=is-1,ie
1858  if (obc%segnum_u(i,j) /= obc_none) then
1859  ubt_sum(i,j) = ubt_sum(i,j) + wt_trans(n) * ubt_trans(i,j)
1860  uhbt_sum(i,j) = uhbt_sum(i,j) + wt_trans(n) * uhbt(i,j)
1861  ubt_wtd(i,j) = ubt_wtd(i,j) + wt_vel(n) * ubt(i,j)
1862  endif
1863  enddo ; enddo ; endif
1864  if (apply_v_obcs) then ; do j=js-1,je ; do i=is,ie
1865  if (obc%segnum_v(i,j) /= obc_none) then
1866  vbt_sum(i,j) = vbt_sum(i,j) + wt_trans(n) * vbt_trans(i,j)
1867  vhbt_sum(i,j) = vhbt_sum(i,j) + wt_trans(n) * vhbt(i,j)
1868  vbt_wtd(i,j) = vbt_wtd(i,j) + wt_vel(n) * vbt(i,j)
1869  endif
1870  enddo ; enddo ; endif
1871  endif
1872 
1873  if (cs%debug_bt) then
1874  call uvchksum("BT [uv]hbt just after OBC", &
1875  uhbt, vhbt, cs%debug_BT_HI, haloshift=iev-ie)
1876  endif
1877 
1878 !$OMP parallel do default(none) shared(isv,iev,jsv,jev,n,eta,eta_src,dtbt,CS,uhbt,vhbt,eta_wtd,wt_eta)
1879  do j=jsv,jev ; do i=isv,iev
1880  eta(i,j) = (eta(i,j) + eta_src(i,j)) + (dtbt * cs%IareaT(i,j)) * &
1881  ((uhbt(i-1,j) - uhbt(i,j)) + (vhbt(i,j-1) - vhbt(i,j)))
1882  eta_wtd(i,j) = eta_wtd(i,j) + eta(i,j) * wt_eta(n)
1883  enddo ; enddo
1884  if (apply_obcs) call apply_eta_obcs(obc, eta, ubt_old, vbt_old, bt_obc, &
1885  g, ms, iev-ie, dtbt)
1886 
1887  if (do_hifreq_output) then
1888  time_step_end = time_bt_start + set_time(int(floor(n*dtbt+0.5)))
1889  call enable_averaging(dtbt, time_step_end, cs%diag)
1890  if (cs%id_ubt_hifreq > 0) call post_data(cs%id_ubt_hifreq, ubt(isdb:iedb,jsd:jed), cs%diag)
1891  if (cs%id_vbt_hifreq > 0) call post_data(cs%id_vbt_hifreq, vbt(isd:ied,jsdb:jedb), cs%diag)
1892  if (cs%id_eta_hifreq > 0) call post_data(cs%id_eta_hifreq, eta(isd:ied,jsd:jed), cs%diag)
1893  if (cs%id_uhbt_hifreq > 0) call post_data(cs%id_uhbt_hifreq, uhbt(isdb:iedb,jsd:jed), cs%diag)
1894  if (cs%id_vhbt_hifreq > 0) call post_data(cs%id_vhbt_hifreq, vhbt(isd:ied,jsdb:jedb), cs%diag)
1895  if (cs%id_eta_pred_hifreq > 0) call post_data(cs%id_eta_pred_hifreq, eta_pf_bt(isd:ied,jsd:jed), cs%diag)
1896  endif
1897 
1898  if (cs%debug_bt) then
1899  write(mesg,'("BT step ",I4)') n
1900  call uvchksum(trim(mesg)//" [uv]bt", &
1901  ubt, vbt, cs%debug_BT_HI, haloshift=iev-ie)
1902  call hchksum(eta, trim(mesg)//" eta", cs%debug_BT_HI, haloshift=iev-ie, scale=gv%H_to_m)
1903  endif
1904 
1905  enddo ! end of do n=1,ntimestep
1906  if (id_clock_calc > 0) call cpu_clock_end(id_clock_calc)
1907  if (id_clock_calc_post > 0) call cpu_clock_begin(id_clock_calc_post)
1908 
1909  ! Reset the time information in the diag type.
1910  if (do_hifreq_output) call enable_averaging(time_int_in, time_end_in, cs%diag)
1911 
1912  i_sum_wt_vel = 1.0 / sum_wt_vel ; i_sum_wt_eta = 1.0 / sum_wt_eta
1913  i_sum_wt_accel = 1.0 / sum_wt_accel ; i_sum_wt_trans = 1.0 / sum_wt_trans
1914 
1915  if (find_etaav) then ; do j=js,je ; do i=is,ie
1916  etaav(i,j) = eta_sum(i,j) * i_sum_wt_accel
1917  enddo ; enddo ; endif
1918  do j=js-1,je+1 ; do i=is-1,ie+1 ; e_anom(i,j) = 0.0 ; enddo ; enddo
1919  if (interp_eta_pf) then
1920  do j=js,je ; do i=is,ie
1921  e_anom(i,j) = dgeo_de * (0.5 * (eta(i,j) + eta_in(i,j)) - &
1922  (eta_pf_1(i,j) + 0.5*d_eta_pf(i,j)))
1923  enddo ; enddo
1924  else
1925  do j=js,je ; do i=is,ie
1926  e_anom(i,j) = dgeo_de * (0.5 * (eta(i,j) + eta_in(i,j)) - eta_pf(i,j))
1927  enddo ; enddo
1928  endif
1929 
1930  ! It is possible that eta_out and eta_in are the same.
1931  do j=js,je ; do i=is,ie
1932  eta_out(i,j) = eta_wtd(i,j) * i_sum_wt_eta
1933  enddo ; enddo
1934 
1935  if (id_clock_calc_post > 0) call cpu_clock_end(id_clock_calc_post)
1936  if (id_clock_pass_post > 0) call cpu_clock_begin(id_clock_pass_post)
1937  if (g%nonblocking_updates) then
1938  pid_e_anom = pass_var_start(e_anom, g%Domain)
1939  else
1940  if (find_etaav) call pass_var(etaav, g%Domain, complete=.false.)
1941  call pass_var(e_anom, g%Domain)
1942  endif
1943  if (id_clock_pass_post > 0) call cpu_clock_end(id_clock_pass_post)
1944  if (id_clock_calc_post > 0) call cpu_clock_begin(id_clock_calc_post)
1945 
1946  do j=js,je ; do i=is-1,ie
1947  cs%ubtav(i,j) = ubt_sum(i,j) * i_sum_wt_trans
1948  uhbtav(i,j) = uhbt_sum(i,j) * i_sum_wt_trans
1949  !### u_accel_bt(I,j) = u_accel_bt(I,j) * I_sum_wt_accel
1950  ubt_wtd(i,j) = ubt_wtd(i,j) * i_sum_wt_vel
1951  enddo ; enddo
1952 
1953  do j=js-1,je ; do i=is,ie
1954  cs%vbtav(i,j) = vbt_sum(i,j) * i_sum_wt_trans
1955  vhbtav(i,j) = vhbt_sum(i,j) * i_sum_wt_trans
1956  !### v_accel_bt(i,J) = v_accel_bt(i,J) * I_sum_wt_accel
1957  vbt_wtd(i,j) = vbt_wtd(i,j) * i_sum_wt_vel
1958  enddo ; enddo
1959 
1960  if (present(uhbt_out)) then
1961  uhbt_out(:,:) = 0.0
1962  if (use_bt_cont) then ; do j=js,je ; do i=is-1,ie
1963  uhbt_out(i,j) = find_uhbt(ubt_wtd(i,j), btcl_u(i,j)) + uhbt0(i,j)
1964  enddo ; enddo ; else ; do j=js,je ; do i=is-1,ie
1965  uhbt_out(i,j) = ubt_wtd(i,j) * datu(i,j) + uhbt0(i,j)
1966  enddo ; enddo ; endif
1967 
1968  vhbt_out(:,:) = 0.0
1969  if (use_bt_cont) then ; do j=js-1,je ; do i=is,ie
1970  vhbt_out(i,j) = find_vhbt(vbt_wtd(i,j), btcl_v(i,j)) + vhbt0(i,j)
1971  enddo ; enddo ; else ; do j=js-1,je ; do i=is,ie
1972  vhbt_out(i,j) = vbt_wtd(i,j) * datv(i,j) + vhbt0(i,j)
1973  enddo ; enddo ; endif
1974  endif
1975 
1976  if (id_clock_calc_post > 0) call cpu_clock_end(id_clock_calc_post)
1977  if (id_clock_pass_post > 0) call cpu_clock_begin(id_clock_pass_post)
1978  if (g%nonblocking_updates) then
1979  call pass_var_complete(pid_e_anom, e_anom, g%Domain)
1980 
1981  if (find_etaav) pid_etaav = pass_var_start(etaav, g%Domain)
1982  pid_uhbtav = pass_vector_start(uhbtav, vhbtav, g%Domain, complete=.false.)
1983  pid_ubtav = pass_vector_start(cs%ubtav, cs%vbtav, g%Domain)
1984  else
1985  call pass_vector(cs%ubtav, cs%vbtav, g%Domain, complete=.false.)
1986  call pass_vector(uhbtav, vhbtav, g%Domain)
1987  endif
1988  if (id_clock_pass_post > 0) call cpu_clock_end(id_clock_pass_post)
1989  if (id_clock_calc_post > 0) call cpu_clock_begin(id_clock_calc_post)
1990 
1991 ! Now calculate each layer's accelerations.
1992 !$OMP parallel do default(none) shared(is,ie,js,je,nz,accel_layer_u,u_accel_bt,pbce,gtot_W, &
1993 !$OMP e_anom,gtot_E,CS,accel_layer_v,v_accel_bt, &
1994 !$OMP gtot_S,gtot_N)
1995  do k=1,nz
1996  do j=js,je ; do i=is-1,ie
1997  accel_layer_u(i,j,k) = u_accel_bt(i,j) - &
1998  ((pbce(i+1,j,k) - gtot_w(i+1,j)) * e_anom(i+1,j) - &
1999  (pbce(i,j,k) - gtot_e(i,j)) * e_anom(i,j)) * cs%IdxCu(i,j)
2000  enddo ; enddo
2001  do j=js-1,je ; do i=is,ie
2002  accel_layer_v(i,j,k) = v_accel_bt(i,j) - &
2003  ((pbce(i,j+1,k) - gtot_s(i,j+1))*e_anom(i,j+1) - &
2004  (pbce(i,j,k) - gtot_n(i,j))*e_anom(i,j)) * cs%IdyCv(i,j)
2005  enddo ; enddo
2006  enddo
2007 
2008  if (id_clock_calc_post > 0) call cpu_clock_end(id_clock_calc_post)
2009 
2010  ! Calculate diagnostic quantities.
2011  if (query_averaging_enabled(cs%diag)) then
2012 
2013  do j=js,je ; do i=is-1,ie ; cs%ubt_IC(i,j) = ubt_wtd(i,j) ; enddo ; enddo
2014  do j=js-1,je ; do i=is,ie ; cs%vbt_IC(i,j) = vbt_wtd(i,j) ; enddo ; enddo
2015  if (present(uhbt_out)) then
2016  do j=js,je ; do i=is-1,ie ; cs%uhbt_IC(i,j) = uhbt_out(i,j) ; enddo ; enddo
2017  do j=js-1,je ; do i=is,ie ; cs%vhbt_IC(i,j) = vhbt_out(i,j) ; enddo ; enddo
2018  elseif (use_bt_cont) then
2019  do j=js,je ; do i=is-1,ie
2020  cs%uhbt_IC(i,j) = find_uhbt(ubt_wtd(i,j), btcl_u(i,j)) + uhbt0(i,j)
2021  enddo ; enddo
2022  do j=js-1,je ; do i=is,ie
2023  cs%vhbt_IC(i,j) = find_vhbt(vbt_wtd(i,j), btcl_v(i,j)) + vhbt0(i,j)
2024  enddo ; enddo
2025  else
2026  do j=js,je ; do i=is-1,ie
2027  cs%uhbt_IC(i,j) = ubt_wtd(i,j) * datu(i,j) + uhbt0(i,j)
2028  enddo ; enddo
2029  do j=js-1,je ; do i=is,ie
2030  cs%vhbt_IC(i,j) = vbt_wtd(i,j) * datv(i,j) + vhbt0(i,j)
2031  enddo ; enddo
2032  endif
2033 
2034 ! Offer various barotropic terms for averaging.
2035  if (cs%id_PFu_bt > 0) then
2036  do j=js,je ; do i=is-1,ie
2037  pfu_bt_sum(i,j) = pfu_bt_sum(i,j) * i_sum_wt_accel
2038  enddo ; enddo
2039  call post_data(cs%id_PFu_bt, pfu_bt_sum(isdb:iedb,jsd:jed), cs%diag)
2040  endif
2041  if (cs%id_PFv_bt > 0) then
2042  do j=js-1,je ; do i=is,ie
2043  pfv_bt_sum(i,j) = pfv_bt_sum(i,j) * i_sum_wt_accel
2044  enddo ; enddo
2045  call post_data(cs%id_PFv_bt, pfv_bt_sum(isd:ied,jsdb:jedb), cs%diag)
2046  endif
2047  if (cs%id_Coru_bt > 0) then
2048  do j=js,je ; do i=is-1,ie
2049  coru_bt_sum(i,j) = coru_bt_sum(i,j) * i_sum_wt_accel
2050  enddo ; enddo
2051  call post_data(cs%id_Coru_bt, coru_bt_sum(isdb:iedb,jsd:jed), cs%diag)
2052  endif
2053  if (cs%id_Corv_bt > 0) then
2054  do j=js-1,je ; do i=is,ie
2055  corv_bt_sum(i,j) = corv_bt_sum(i,j) * i_sum_wt_accel
2056  enddo ; enddo
2057  call post_data(cs%id_Corv_bt, corv_bt_sum(isd:ied,jsdb:jedb), cs%diag)
2058  endif
2059  if (cs%id_ubtforce > 0) call post_data(cs%id_ubtforce, bt_force_u(isdb:iedb,jsd:jed), cs%diag)
2060  if (cs%id_vbtforce > 0) call post_data(cs%id_vbtforce, bt_force_v(isd:ied,jsdb:jedb), cs%diag)
2061  if (cs%id_uaccel > 0) call post_data(cs%id_uaccel, u_accel_bt(isdb:iedb,jsd:jed), cs%diag)
2062  if (cs%id_vaccel > 0) call post_data(cs%id_vaccel, v_accel_bt(isd:ied,jsdb:jedb), cs%diag)
2063  if (cs%id_Datu_res > 0) call post_data(cs%id_Datu_res, cs%Datu_res(isdb:iedb,jsd:jed), cs%diag)
2064  if (cs%id_Datv_res > 0) call post_data(cs%id_Datv_res, cs%Datv_res(isd:ied,jsdb:jedb), cs%diag)
2065 
2066  if (cs%id_eta_cor > 0) call post_data(cs%id_eta_cor, cs%eta_cor, cs%diag)
2067  if (cs%id_eta_bt > 0) call post_data(cs%id_eta_bt, eta_out, cs%diag)
2068  if (cs%id_gtotn > 0) call post_data(cs%id_gtotn, gtot_n(isd:ied,jsd:jed), cs%diag)
2069  if (cs%id_gtots > 0) call post_data(cs%id_gtots, gtot_s(isd:ied,jsd:jed), cs%diag)
2070  if (cs%id_gtote > 0) call post_data(cs%id_gtote, gtot_e(isd:ied,jsd:jed), cs%diag)
2071  if (cs%id_gtotw > 0) call post_data(cs%id_gtotw, gtot_w(isd:ied,jsd:jed), cs%diag)
2072  if (cs%id_ubt > 0) call post_data(cs%id_ubt, ubt_wtd(isdb:iedb,jsd:jed), cs%diag)
2073  if (cs%id_vbt > 0) call post_data(cs%id_vbt, vbt_wtd(isd:ied,jsdb:jedb), cs%diag)
2074  if (cs%id_ubtav > 0) call post_data(cs%id_ubtav, cs%ubtav, cs%diag)
2075  if (cs%id_vbtav > 0) call post_data(cs%id_vbtav, cs%vbtav, cs%diag)
2076  if (use_visc_rem) then
2077  if (cs%id_visc_rem_u > 0) call post_data(cs%id_visc_rem_u, visc_rem_u, cs%diag)
2078  if (cs%id_visc_rem_v > 0) call post_data(cs%id_visc_rem_v, visc_rem_v, cs%diag)
2079  endif
2080 
2081  if (cs%id_frhatu > 0) call post_data(cs%id_frhatu, cs%frhatu, cs%diag)
2082  if (cs%id_uhbt > 0) call post_data(cs%id_uhbt, uhbtav, cs%diag)
2083  if (cs%id_frhatv > 0) call post_data(cs%id_frhatv, cs%frhatv, cs%diag)
2084  if (cs%id_vhbt > 0) call post_data(cs%id_vhbt, vhbtav, cs%diag)
2085 
2086  if (cs%id_frhatu1 > 0) call post_data(cs%id_frhatu1, cs%frhatu1, cs%diag)
2087  if (cs%id_frhatv1 > 0) call post_data(cs%id_frhatv1, cs%frhatv1, cs%diag)
2088  else
2089  if (cs%id_frhatu1 > 0) cs%frhatu1(:,:,:) = cs%frhatu(:,:,:)
2090  if (cs%id_frhatv1 > 0) cs%frhatv1(:,:,:) = cs%frhatv(:,:,:)
2091  endif
2092 
2093  if (g%nonblocking_updates) then
2094  if (find_etaav) call pass_var_complete(pid_etaav, etaav, g%Domain)
2095  call pass_vector_complete(pid_uhbtav, uhbtav, vhbtav, g%Domain)
2096  call pass_vector_complete(pid_ubtav, cs%ubtav, cs%vbtav, g%Domain)
2097  endif
2098 
2099  if (apply_obcs) call destroy_bt_obc(bt_obc)
2100 
2101 end subroutine legacy_btstep
2102 
2103 subroutine legacy_set_dtbt(G, GV, CS, eta, pbce, BT_cont, gtot_est, SSH_add)
2104  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
2105  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid
2106  !! structure.
2107  type(legacy_barotropic_cs), pointer :: CS !< The control structure returned
2108  !! by a previous call to barotropic_init.
2109  real, dimension(SZI_(G),SZJ_(G)), &
2110  intent(in), optional :: eta !< The barotropic free surface
2111  !! height anomaly or column mass anomaly, in m or kg m-2.
2112  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
2113  intent(in), optional :: pbce !< The baroclinic pressure anomaly
2114  !! in each layer due to free surface height anomalies, in m2 H-1 s-2.
2115  type(bt_cont_type), pointer, optional :: BT_cont !< A structure with elements that
2116  !! describe the effective open face areas as a function of barotropic flow.
2117  real, intent(in), optional :: gtot_est !< An estimate of the total
2118  !! gravitational acceleration, in m s-2.
2119  real, intent(in), optional :: SSH_add !< An additional contribution to
2120  !! SSH to provide a margin of error when calculating the external wave speed, in m
2121 
2122 ! Arguments: G - The ocean's grid structure.
2123 ! (in) GV - The ocean's vertical grid structure.
2124 ! (in) CS - The control structure returned by a previous call to
2125 ! barotropic_init.
2126 ! (in,opt) eta - The barotropic free surface height anomaly or
2127 ! column mass anomaly, in m or kg m-2.
2128 ! (in,opt) pbce - The baroclinic pressure anomaly in each layer
2129 ! due to free surface height anomalies, in m2 H-1 s-2.
2130 ! (in,opt) BT_cont - A structure with elements that describe the effective
2131 ! open face areas as a function of barotropic flow.
2132 ! (in,opt) gtot_est - An estimate of the total gravitational acceleration,
2133 ! in m s-2.
2134 ! (in,opt) SSH_add - An additional contribution to SSH to provide a margin of
2135 ! error when calculating the external wave speed, in m.
2136  ! This subroutine automatically determines an optimal value for dtbt based
2137  ! on some state of the ocean.
2138  real, dimension(SZI_(G),SZJ_(G)) :: &
2139  gtot_E, & ! gtot_X is the effective total reduced gravity used to relate
2140  gtot_W, & ! free surface height deviations to pressure forces (including
2141  gtot_N, & ! GFS and baroclinic contributions) in the barotropic momentum
2142  gtot_S ! equations half a grid-point in the X-direction (X is N, S,
2143  ! E, or W) from the thickness point. gtot_X has units of m2 H-1 s-2.
2144  ! (See Hallberg, J Comp Phys 1997 for a discussion.)
2145  real, dimension(SZIBS_(G),SZJ_(G)) :: &
2146  Datu ! Basin depth at u-velocity grid points times the y-grid
2147  ! spacing, in m2.
2148  real, dimension(SZI_(G),SZJBS_(G)) :: &
2149  Datv ! Basin depth at v-velocity grid points times the x-grid
2150  ! spacing, in m2.
2151  real :: det_de ! The partial derivative due to self-attraction and loading
2152  ! of the reference geopotential with the sea surface height.
2153  ! This is typically ~0.09 or less.
2154  real :: dgeo_de ! The constant of proportionality between geopotential and
2155  ! sea surface height. It is a nondimensional number of
2156  ! order 1. For stability, this may be made larger
2157  ! than physical problem would suggest.
2158  real :: add_SSH ! An additional contribution to SSH to provide a margin of error
2159  ! when calculating the external wave speed, in m.
2160  real :: min_max_dt2, Idt_max2, dtbt_max
2161  logical :: use_BT_cont
2162  type(memory_size_type) :: MS
2163 
2164  character(len=200) :: mesg
2165  integer :: i, j, k, is, ie, js, je, nz
2166 
2167  if (.not.associated(cs)) call mom_error(fatal, &
2168  "legacy_set_dtbt: Module MOM_barotropic must be initialized before it is used.")
2169  if (.not.cs%split) return
2170  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
2171  ms%isdw = g%isd ; ms%iedw = g%ied ; ms%jsdw = g%jsd ; ms%jedw = g%jed
2172 
2173  if (.not.(present(pbce) .or. present(gtot_est))) call mom_error(fatal, &
2174  "legacy_set_dtbt: Either pbce or gtot_est must be present.")
2175 
2176  add_ssh = 0.0 ; if (present(ssh_add)) add_ssh = ssh_add
2177 
2178  use_bt_cont = .false.
2179  if (present(bt_cont)) use_bt_cont = (associated(bt_cont))
2180 
2181  if (use_bt_cont) then
2182  call bt_cont_to_face_areas(bt_cont, datu, datv, g, ms, 0, .true.)
2183  elseif (cs%Nonlinear_continuity .and. present(eta)) then
2184  call find_face_areas(datu, datv, g, gv, cs, ms, eta=eta, halo=0)
2185  else
2186  call find_face_areas(datu, datv, g, gv, cs, ms, halo=0, add_max=add_ssh)
2187  endif
2188 
2189  det_de = 0.0
2190  if (cs%tides) call tidal_forcing_sensitivity(g, cs%tides_CSp, det_de)
2191  dgeo_de = 1.0 + max(0.0, det_de + cs%G_extra)
2192  if (present(pbce)) then
2193  do j=js,je ; do i=is,ie
2194  gtot_e(i,j) = 0.0 ; gtot_w(i,j) = 0.0
2195  gtot_n(i,j) = 0.0 ; gtot_s(i,j) = 0.0
2196  enddo ; enddo
2197  do k=1,nz ; do j=js,je ; do i=is,ie
2198  gtot_e(i,j) = gtot_e(i,j) + pbce(i,j,k) * cs%frhatu(i,j,k)
2199  gtot_w(i,j) = gtot_w(i,j) + pbce(i,j,k) * cs%frhatu(i-1,j,k)
2200  gtot_n(i,j) = gtot_n(i,j) + pbce(i,j,k) * cs%frhatv(i,j,k)
2201  gtot_s(i,j) = gtot_s(i,j) + pbce(i,j,k) * cs%frhatv(i,j-1,k)
2202  enddo ; enddo ; enddo
2203  else
2204  do j=js,je ; do i=is,ie
2205  gtot_e(i,j) = gtot_est * gv%H_to_m ; gtot_w(i,j) = gtot_est * gv%H_to_m
2206  gtot_n(i,j) = gtot_est * gv%H_to_m ; gtot_s(i,j) = gtot_est * gv%H_to_m
2207  enddo ; enddo
2208  endif
2209 
2210  min_max_dt2 = 1.0e38 ! A huge number.
2211  do j=js,je ; do i=is,ie
2212  ! This is pretty accurate for gravity waves, but it is a conservative
2213  ! estimate since it ignores the stabilizing effect of the bottom drag.
2214  idt_max2 = 0.5 * (1.0 + 2.0*cs%bebt) * (g%IareaT(i,j) * &
2215  ((gtot_e(i,j)*datu(i,j)*g%IdxCu(i,j) + gtot_w(i,j)*datu(i-1,j)*g%IdxCu(i-1,j)) + &
2216  (gtot_n(i,j)*datv(i,j)*g%IdyCv(i,j) + gtot_s(i,j)*datv(i,j-1)*g%IdyCv(i,j-1))) + &
2217  ((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
2218  (g%CoriolisBu(i-1,j)**2 + g%CoriolisBu(i,j-1)**2)))
2219  if (idt_max2 * min_max_dt2 > 1.0) min_max_dt2 = 1.0 / idt_max2
2220  enddo ; enddo
2221  dtbt_max = sqrt(min_max_dt2 / dgeo_de)
2222  if (id_clock_sync > 0) call cpu_clock_begin(id_clock_sync)
2223  call min_across_pes(dtbt_max)
2224  if (id_clock_sync > 0) call cpu_clock_end(id_clock_sync)
2225 
2226  cs%dtbt = cs%dtbt_fraction * dtbt_max
2227  cs%dtbt_max = dtbt_max
2228 end subroutine legacy_set_dtbt
2229 
2230 ! The following 4 subroutines apply the open boundary conditions.
2231 !> This subroutine applies the open boundary conditions on barotropic
2232 !! velocities and mass transports, as developed by Mehmet Ilicak.
2233 subroutine apply_velocity_obcs(OBC, ubt, vbt, uhbt, vhbt, ubt_trans, vbt_trans, &
2234  eta, ubt_old, vbt_old, BT_OBC, &
2235  G, MS, halo, dtbt, bebt, use_BT_cont, Datu, Datv, &
2236  BTCL_u, BTCL_v, uhbt0, vhbt0)
2237  type(ocean_obc_type), pointer :: OBC !< An associated pointer to an
2238  !! OBC type.
2239  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
2240  type(memory_size_type), intent(in) :: MS !< A type that describes the
2241  !! memory sizes of the argument arrays.
2242  real, dimension(SZIBW_(MS),SZJW_(MS)), intent(inout) :: ubt !< The zonal barotropic velocity,
2243  !! in m s-1.
2244  real, dimension(SZIBW_(MS),SZJW_(MS)), intent(inout) :: uhbt !< The zonal barotropic transport,
2245  !! in H m2 s-1.
2246  real, dimension(SZIBW_(MS),SZJW_(MS)), intent(inout) :: ubt_trans !< The zonal barotropic velocity
2247  !! used in transport, m s-1.
2248  real, dimension(SZIW_(MS),SZJBW_(MS)), intent(inout) :: vbt !< The meridional barotropic
2249  !! velocity, in m s-1.
2250  real, dimension(SZIW_(MS),SZJBW_(MS)), intent(inout) :: vhbt !< The meridional barotropic
2251  !! transport, in H m2 s-1.
2252  real, dimension(SZIW_(MS),SZJBW_(MS)), intent(inout) :: vbt_trans !< The meridional BT velocity
2253  !! used in transports, m s-1.
2254  real, dimension(SZIW_(MS),SZJW_(MS)), intent(in) :: eta !< The barotropic free surface
2255  !! height anomaly or column mass anomaly, in m or kg m-2.
2256  real, dimension(SZIBW_(MS),SZJW_(MS)), intent(in) :: ubt_old !< The starting value of ubt in a
2257  !! barotropic step, m s-1.
2258  real, dimension(SZIW_(MS),SZJBW_(MS)), intent(in) :: vbt_old !< The starting value of ubt in a
2259  !! barotropic step, m s-1.
2260  type(bt_obc_type), intent(in) :: BT_OBC !< A structure with the private
2261  !! barotropic arrays related to the open
2262  !! boundary conditions, set by set_up_BT_OBC.
2263  integer, intent(in) :: halo !< The extra halo size to
2264  !! use here.
2265  real, intent(in) :: dtbt !< The time step, in s.
2266  real, intent(in) :: bebt !< The fractional weighting of
2267  !! the future velocity in determining the transport.
2268  logical, intent(in) :: use_BT_cont !< If true, use the
2269  !! BT_cont_types to calculate transports.
2270  real, dimension(SZIBW_(MS),SZJW_(MS)), intent(in) :: Datu !< A fixed estimate of the face
2271  !! areas at u points.
2272  real, dimension(SZIW_(MS),SZJBW_(MS)), intent(in) :: Datv !< A fixed estimate of the face
2273  !! areas at u points.
2274  type(local_bt_cont_u_type), dimension(SZIBW_(MS),SZJW_(MS)), &
2275  intent(in) :: BTCL_u !< Structures of information used
2276  !! for a dynamic estimate of the face areas at u- points.
2277  type(local_bt_cont_v_type), dimension(SZIW_(MS),SZJBW_(MS)), &
2278  intent(in) :: BTCL_v !< Structures of information used
2279  !! for a dynamic estimate of the face areas at v- points.
2280  real, dimension(SZIBW_(MS),SZJW_(MS)), intent(in) :: uhbt0
2281  real, dimension(SZIW_(MS),SZJBW_(MS)), intent(in) :: vhbt0
2282 ! This subroutine applies the open boundary conditions on barotropic
2283 ! velocities and mass transports, as developed by Mehmet Ilicak.
2284 
2285 ! Arguments: OBC - an associated pointer to an OBC type.
2286 ! (inout) ubt - the zonal barotropic velocity, in m s-1.
2287 ! (inout) vbt - the meridional barotropic velocity, in m s-1.
2288 ! (inout) uhbt - the zonal barotropic transport, in H m2 s-1.
2289 ! (inout) vhbt - the meridional barotropic transport, in H m2 s-1.
2290 ! (inout) ubt_trans - the zonal barotropic velocity used in transport, m s-1.
2291 ! (inout) vbt_trans - the meridional BT velocity used in transports, m s-1.
2292 ! (in) eta - The barotropic free surface height anomaly or
2293 ! column mass anomaly, in m or kg m-2.
2294 ! (in) ubt_old - The starting value of ubt in a barotropic step, m s-1.
2295 ! (in) vbt_old - The starting value of ubt in a barotropic step, m s-1.
2296 ! (in) BT_OBC - A structure with the private barotropic arrays related
2297 ! to the open boundary conditions, set by set_up_BT_OBC.
2298 ! (in) G - The ocean's grid structure.
2299 ! (in) MS - A type that describes the memory sizes of the argument arrays.
2300 ! (in) halo - The extra halo size to use here.
2301 ! (in) dtbt - The time step, in s.
2302 ! (in) bebt - The fractional weighting of the future velocity in
2303 ! determining the transport.
2304 ! (in) use_BT_cont - If true, use the BT_cont_types to calculate transports.
2305 ! (in) Datu - A fixed estimate of the face areas at u points.
2306 ! (in) Datv - A fixed estimate of the face areas at u points.
2307 ! (in) BCTL_u - Structures of information used for a dynamic estimate
2308 ! (in) BCTL_v - of the face areas at u- and v- points.
2309  real :: vel_prev ! The previous velocity in m s-1.
2310  real :: vel_trans ! The combination of the previous and current velocity
2311  ! that does the mass transport, in m s-1.
2312  real :: H_u ! The total thickness at the u-point, in m or kg m-2.
2313  real :: H_v ! The total thickness at the v-point, in m or kg m-2.
2314  real :: cfl ! The CFL number at the point in question, ND.
2315  real :: u_inlet
2316  real :: v_inlet
2317  real :: h_in
2318  integer :: i, j, is, ie, js, je
2319  is = g%isc-halo ; ie = g%iec+halo ; js = g%jsc-halo ; je = g%jec+halo
2320 
2321  if (apply_u_obcs) then
2322  do j=js,je ; do i=is-1,ie ; if (obc%segnum_u(i,j) /= obc_none) then
2323  if (obc%segment(obc%segnum_u(i,j))%specified) then
2324  uhbt(i,j) = bt_obc%uhbt(i,j)
2325  ubt(i,j) = bt_obc%ubt_outer(i,j)
2326  vel_trans = ubt(i,j)
2327  elseif (obc%segment(obc%segnum_u(i,j))%Flather) then
2328  if (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_e) then
2329  cfl = dtbt * bt_obc%Cg_u(i,j) * g%IdxCu(i,j) ! CFL
2330  u_inlet = cfl*ubt_old(i-1,j) + (1.0-cfl)*ubt_old(i,j) ! Valid for cfl<1
2331  ! h_in = 2.0*cfl*eta(i,j) + (1.0-2.0*cfl)*eta(i+1,j) ! external
2332  h_in = eta(i,j) + (0.5-cfl)*(eta(i,j)-eta(i-1,j)) ! internal
2333 
2334  h_u = bt_obc%H_u(i,j)
2335  vel_prev = ubt(i,j)
2336  ubt(i,j) = 0.5*((u_inlet + bt_obc%ubt_outer(i,j)) + &
2337  (bt_obc%Cg_u(i,j)/h_u) * (h_in-bt_obc%eta_outer_u(i,j)))
2338 
2339  vel_trans = (1.0-bebt)*vel_prev + bebt*ubt(i,j)
2340  elseif (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_w) then
2341  cfl = dtbt * bt_obc%Cg_u(i,j) * g%IdxCu(i,j) ! CFL
2342  u_inlet = cfl*ubt_old(i+1,j) + (1.0-cfl)*ubt_old(i,j) ! Valid for cfl<1
2343  ! h_in = 2.0*cfl*eta(i+1,j) + (1.0-2.0*cfl)*eta(i,j) ! external
2344  h_in = eta(i+1,j) + (0.5-cfl)*(eta(i+1,j)-eta(i+2,j)) ! internal
2345 
2346  h_u = bt_obc%H_u(i,j)
2347  vel_prev = ubt(i,j)
2348  ubt(i,j) = 0.5*((u_inlet+bt_obc%ubt_outer(i,j)) + &
2349  (bt_obc%Cg_u(i,j)/h_u) * (bt_obc%eta_outer_u(i,j)-h_in))
2350 
2351  vel_trans = (1.0-bebt)*vel_prev + bebt*ubt(i,j)
2352  elseif (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_n) then
2353  if ((vbt(i,j-1)+vbt(i+1,j-1)) > 0.0) then
2354  ubt(i,j) = 2.0*ubt(i,j-1)-ubt(i,j-2)
2355  else
2356  ubt(i,j) = bt_obc%ubt_outer(i,j)
2357  endif
2358  vel_trans = ubt(i,j)
2359  elseif (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_s) then
2360  if ((vbt(i,j)+vbt(i+1,j)) < 0.0) then
2361  ubt(i,j) = 2.0*ubt(i,j+1)-ubt(i,j+2)
2362  else
2363  ubt(i,j) = bt_obc%ubt_outer(i,j)
2364  endif
2365  vel_trans = ubt(i,j)
2366  endif
2367  endif
2368 
2369  if (.not. obc%segment(obc%segnum_u(i,j))%specified) then
2370  if (use_bt_cont) then
2371  uhbt(i,j) = find_uhbt(vel_trans,btcl_u(i,j)) + uhbt0(i,j)
2372  else
2373  uhbt(i,j) = datu(i,j)*vel_trans + uhbt0(i,j)
2374  endif
2375  endif
2376 
2377  ubt_trans(i,j) = vel_trans
2378  endif ; enddo ; enddo
2379  endif
2380 
2381  if (apply_v_obcs) then
2382  do j=js-1,je ; do i=is,ie ; if (obc%segnum_v(i,j) /= obc_none) then
2383  if (obc%segment(obc%segnum_v(i,j))%specified) then
2384  vhbt(i,j) = bt_obc%vhbt(i,j)
2385  vbt(i,j) = bt_obc%vbt_outer(i,j)
2386  vel_trans = vbt(i,j)
2387  elseif (obc%segment(obc%segnum_v(i,j))%Flather) then
2388  if (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_n) then
2389  cfl = dtbt * bt_obc%Cg_v(i,j) * g%IdyCv(i,j) ! CFL
2390  v_inlet = cfl*vbt_old(i,j-1) + (1.0-cfl)*vbt_old(i,j) ! Valid for cfl<1
2391  ! h_in = 2.0*cfl*eta(i,j) + (1.0-2.0*cfl)*eta(i,j+1) ! external
2392  h_in = eta(i,j) + (0.5-cfl)*(eta(i,j)-eta(i,j-1)) ! internal
2393 
2394  h_v = bt_obc%H_v(i,j)
2395  vel_prev = vbt(i,j)
2396  vbt(i,j) = 0.5*((v_inlet+bt_obc%vbt_outer(i,j)) + &
2397  (bt_obc%Cg_v(i,j)/h_v) * (h_in-bt_obc%eta_outer_v(i,j)))
2398 
2399  vel_trans = (1.0-bebt)*vel_prev + bebt*vbt(i,j)
2400  elseif (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_s) then
2401  cfl = dtbt * bt_obc%Cg_v(i,j) * g%IdyCv(i,j) ! CFL
2402  v_inlet = cfl*vbt_old(i,j+1) + (1.0-cfl)*vbt_old(i,j) ! Valid for cfl <1
2403  ! h_in = 2.0*cfl*eta(i,j+1) + (1.0-2.0*cfl)*eta(i,j) ! external
2404  h_in = eta(i,j+1) + (0.5-cfl)*(eta(i,j+1)-eta(i,j+2)) ! internal
2405 
2406  h_v = bt_obc%H_v(i,j)
2407  vel_prev = vbt(i,j)
2408  vbt(i,j) = 0.5*((v_inlet+bt_obc%vbt_outer(i,j)) + &
2409  (bt_obc%Cg_v(i,j)/h_v) * (bt_obc%eta_outer_v(i,j)-h_in))
2410 
2411  vel_trans = (1.0-bebt)*vel_prev + bebt*vbt(i,j)
2412  elseif (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_e) then
2413  if ((ubt(i-1,j)+ubt(i-1,j+1)) > 0.0) then
2414  vbt(i,j) = 2.0*vbt(i-1,j)-vbt(i-2,j)
2415  else
2416  vbt(i,j) = bt_obc%vbt_outer(i,j)
2417  endif
2418  vel_trans = vbt(i,j)
2419 !!!!!!!!!!!!!!!!!!! CLAMPED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2420 ! cfl = dtbt * BT_OBC%Cg_v(i,J) * G%IdyCv(i,J) !
2421 ! vbt(i,J) = (vbt(i-1,J) + CFL*vbt(i,J)) / (1.0 + CFL) !
2422 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2423  elseif (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_w) then
2424  if ((ubt(i,j)+ubt(i,j+1)) < 0.0) then
2425  vbt(i,j) = 2.0*vbt(i+1,j)-vbt(i+2,j)
2426  else
2427  vbt(i,j) = bt_obc%vbt_outer(i,j)
2428  endif
2429  vel_trans = vbt(i,j)
2430 !!!!!!!!!!!!!!!!!! CLAMPED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2431 ! cfl = dtbt * BT_OBC%Cg_v(i,J) * G%IdyCv(i,J) !
2432 ! vbt(i,J) = (vbt(i-1,J) + CFL*vbt(i,J)) / (1.0 + CFL) !
2433 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2434  endif
2435  endif
2436 
2437  if (obc%segnum_v(i,j) /= obc_simple) then
2438  if (use_bt_cont) then
2439  vhbt(i,j) = find_vhbt(vel_trans,btcl_v(i,j)) + vhbt0(i,j)
2440  else
2441  vhbt(i,j) = vel_trans*datv(i,j) + vhbt0(i,j)
2442  endif
2443  endif
2444 
2445  vbt_trans(i,j) = vel_trans
2446  endif ; enddo ; enddo
2447  endif
2448 
2449 end subroutine apply_velocity_obcs
2450 
2451 !> This subroutine applies the open boundary conditions on the free surface
2452 !! height, as coded by Mehmet Ilicak.
2453 subroutine apply_eta_obcs(OBC, eta, ubt, vbt, BT_OBC, G, MS, halo, dtbt)
2454  type(ocean_obc_type), pointer :: OBC !< An associated pointer to
2455  !! an OBC type.
2456  type(memory_size_type), intent(in) :: MS !< A type that describes the memory
2457  !! sizes of the argument arrays.
2458  real, dimension(SZIW_(MS),SZJW_(MS)), intent(inout) :: eta !< The barotropic free surface height
2459  !! anomaly or column mass anomaly, in m or kg m-2.
2460  real, dimension(SZIBW_(MS),SZJW_(MS)), intent(in) :: ubt !< The zonal barotropic velocity,
2461  !! in m s-1.
2462  real, dimension(SZIW_(MS),SZJBW_(MS)), intent(in) :: vbt !< The meridional barotropic
2463  !! velocity, in m s-1.
2464  type(bt_obc_type), intent(in) :: BT_OBC !<A structure with the private
2465  !! barotropic arrays related to the open
2466  !! boundary conditions, set by set_up_BT_OBC.
2467  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
2468  integer, intent(in) :: halo !< The extra halo size to use here.
2469  real, intent(in) :: dtbt !< The time step, in s.
2470 ! This subroutine applies the open boundary conditions on the free surface
2471 ! height, as coded by Mehmet Ilicak.
2472 
2473 ! Arguments: OBC - an associated pointer to an OBC type.
2474 ! (inout) eta - The barotropic free surface height anomaly or
2475 ! column mass anomaly, in m or kg m-2.
2476 ! (inout) ubt - the zonal barotropic velocity, in m s-1.
2477 ! (inout) vbt - the meridional barotropic velocity, in m s-1.
2478 ! (in) G - The ocean's grid structure.
2479 ! (in) MS - A type that describes the memory sizes of the argument arrays.
2480 ! (in) halo - The extra halo size to use here.
2481 ! (in) dtbt - The time step, in s.
2482 
2483  real :: H_u ! The total thickness at the u-point, in m or kg m-2.
2484  real :: H_v ! The total thickness at the v-point, in m or kg m-2.
2485  real :: cfl ! The CFL number at the point in question, ND.
2486  real :: u_inlet
2487  real :: v_inlet
2488  real :: h_in
2489  integer :: i, j, is, ie, js, je
2490  is = g%isc-halo ; ie = g%iec+halo ; js = g%jsc-halo ; je = g%jec+halo
2491 
2492  if ((obc%Flather_u_BCs_exist_globally) .and. apply_u_obcs) then
2493  do j=js,je ; do i=is-1,ie ; if (obc%segnum_u(i,j) /= obc_none) then
2494  if (obc%segment(obc%segnum_u(i,j))%Flather) then
2495  if (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_e) then
2496  cfl = dtbt * bt_obc%Cg_u(i,j) * g%IdxCu(i,j) ! CFL
2497  u_inlet = cfl*ubt(i-1,j) + (1.0-cfl)*ubt(i,j) ! Valid for cfl <1
2498 ! h_in = 2.0*cfl*eta(i,j) + (1.0-2.0*cfl)*eta(i+1,j) ! external
2499  h_in = eta(i,j) + (0.5-cfl)*(eta(i,j)-eta(i-1,j)) ! internal
2500 
2501  h_u = bt_obc%H_u(i,j)
2502  eta(i+1,j) = 2.0 * 0.5*((bt_obc%eta_outer_u(i,j)+h_in) + &
2503  (h_u/bt_obc%Cg_u(i,j))*(u_inlet-bt_obc%ubt_outer(i,j))) - eta(i,j)
2504  elseif (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_w) then
2505  cfl = dtbt*bt_obc%Cg_u(i,j)*g%IdxCu(i,j) ! CFL
2506  u_inlet = cfl*ubt(i+1,j) + (1.0-cfl)*ubt(i,j) ! Valid for cfl <1
2507 ! h_in = 2.0*cfl*eta(i+1,j) + (1.0-2.0*cfl)*eta(i,j) ! external
2508  h_in = eta(i+1,j) + (0.5-cfl)*(eta(i+1,j)-eta(i+2,j)) ! internal
2509 
2510  h_u = bt_obc%H_u(i,j)
2511  eta(i,j) = 2.0 * 0.5*((bt_obc%eta_outer_u(i,j)+h_in) + &
2512  (h_u/bt_obc%Cg_u(i,j))*(bt_obc%ubt_outer(i,j)-u_inlet)) - eta(i+1,j)
2513  endif
2514  endif
2515  endif ; enddo ; enddo
2516  endif
2517 
2518  if ((obc%Flather_v_BCs_exist_globally) .and. apply_v_obcs) then
2519  do j=js-1,je ; do i=is,ie ; if (obc%segnum_v(i,j) /= obc_none) then
2520  if (obc%segment(obc%segnum_v(i,j))%Flather) then
2521  if (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_n) then
2522  cfl = dtbt*bt_obc%Cg_v(i,j)*g%IdyCv(i,j) ! CFL
2523  v_inlet = cfl*vbt(i,j-1) + (1.0-cfl)*vbt(i,j) ! Valid for cfl <1
2524 ! h_in = 2.0*cfl*eta(i,j) + (1.0-2.0*cfl)*eta(i,j+1) ! external
2525  h_in = eta(i,j) + (0.5-cfl)*(eta(i,j)-eta(i,j-1)) ! internal
2526 
2527  h_v = bt_obc%H_v(i,j)
2528  eta(i,j+1) = 2.0 * 0.5*((bt_obc%eta_outer_v(i,j)+h_in) + &
2529  (h_v/bt_obc%Cg_v(i,j))*(v_inlet-bt_obc%vbt_outer(i,j))) - eta(i,j)
2530  elseif (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_s) then
2531  cfl = dtbt*bt_obc%Cg_v(i,j)*g%IdyCv(i,j) ! CFL
2532  v_inlet = cfl*vbt(i,j+1) + (1.0-cfl)*vbt(i,j) ! Valid for cfl <1
2533 ! h_in = 2.0*cfl*eta(i,j+1) + (1.0-2.0*cfl)*eta(i,j) ! external
2534  h_in = eta(i,j+1) + (0.5-cfl)*(eta(i,j+1)-eta(i,j+2)) ! internal
2535 
2536  h_v = bt_obc%H_v(i,j)
2537  eta(i,j) = 2.0 * 0.5*((bt_obc%eta_outer_v(i,j)+h_in) + &
2538  (h_v/bt_obc%Cg_v(i,j))*(bt_obc%vbt_outer(i,j)-v_inlet)) - eta(i,j+1)
2539  endif
2540  endif
2541  endif ; enddo ; enddo
2542  endif
2543 
2544 end subroutine apply_eta_obcs
2545 !> This subroutine sets up the private structure used to apply the open
2546 !! boundary conditions, as developed by Mehmet Ilicak.
2547 subroutine set_up_bt_obc(OBC, eta, BT_OBC, G, GV, MS, halo, use_BT_cont, Datu, Datv, BTCL_u, BTCL_v)
2548  type(ocean_obc_type), pointer :: OBC !< An associated pointer to an
2549  !! OBC type.
2550  type(memory_size_type), intent(in) :: MS !< A type that describes the memory
2551  !! sizes of the argument arrays.
2552  real, dimension(SZIW_(MS),SZJW_(MS)), intent(in) :: eta !< The barotropic free surface
2553  !! height anomaly or column mass anomaly, in m or kg m-2.
2554  type(bt_obc_type), intent(inout) :: BT_OBC !< A structure with the private
2555  !! barotropic arrays related to the open
2556  !! boundary conditions, set by set_up_BT_OBC.
2557  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
2558  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid
2559  !! structure.
2560  integer, intent(in) :: halo !< The extra halo size to use here.
2561  logical, intent(in) :: use_BT_cont !< If true, use the
2562  !! BT_cont_types to calculate transports.
2563  real, dimension(SZIBW_(MS),SZJW_(MS)), intent(in) :: Datu !< A fixed estimate of the face
2564  !! areas at u points.
2565  real, dimension(SZIW_(MS),SZJBW_(MS)), intent(in) :: Datv !< A fixed estimate of the face
2566  !! areas at v points.
2567  type(local_bt_cont_u_type), dimension(SZIBW_(MS),SZJW_(MS)), &
2568  intent(in) :: BTCL_u !< Structures of information used
2569  !! for a dynamic estimate of the face areas at u- points.
2570  type(local_bt_cont_v_type), dimension(SZIW_(MS),SZJBW_(MS)), &
2571  intent(in) :: BTCL_v !< Structures of information used
2572  !! for a dynamic estimate of the face areas at v- points.
2573 ! This subroutine sets up the private structure used to apply the open
2574 ! boundary conditions, as developed by Mehmet Ilicak.
2575 
2576 ! Arguments: OBC - an associated pointer to an OBC type.
2577 ! (in) eta - The barotropic free surface height anomaly or
2578 ! column mass anomaly, in m or kg m-2.
2579 ! (in) BT_OBC - A structure with the private barotropic arrays related
2580 ! to the open boundary conditions, set by set_up_BT_OBC.
2581 ! (in) G - The ocean's grid structure.
2582 ! (in) GV - The ocean's vertical grid structure.
2583 ! (in) MS - A type that describes the memory sizes of the argument arrays.
2584 ! (in) halo - The extra halo size to use here.
2585 ! (in) dtbt - The time step, in s.
2586 ! (in) use_BT_cont - If true, use the BT_cont_types to calculate transports.
2587 ! (in) Datu - A fixed estimate of the face areas at u points.
2588 ! (in) Datv - A fixed estimate of the face areas at u points.
2589 ! (in) BCTL_u - Structures of information used for a dynamic estimate
2590 ! (in) BCTL_v - of the face areas at u- and v- points.
2591 
2592  integer :: i, j, k, is, ie, js, je, nz, Isq, Ieq, Jsq, Jeq, n
2593  integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB
2594  integer :: isdw, iedw, jsdw, jedw
2595  logical :: OBC_used
2596  type(obc_segment_type), pointer :: segment !< Open boundary segment
2597 
2598  is = g%isc-halo ; ie = g%iec+halo ; js = g%jsc-halo ; je = g%jec+halo
2599  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = g%ke
2600  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
2601  isdw = ms%isdw ; iedw = ms%iedw ; jsdw = ms%jsdw ; jedw = ms%jedw
2602 
2603  if ((isdw < isd) .or. (jsdw < jsd)) then
2604  call mom_error(fatal, "set_up_BT_OBC: Open boundary conditions are not "//&
2605  "yet fully implemented with wide barotropic halos.")
2606  endif
2607 
2608  allocate(bt_obc%Cg_u(isdw-1:iedw,jsdw:jedw)) ; bt_obc%Cg_u(:,:) = 0.0
2609  allocate(bt_obc%H_u(isdw-1:iedw,jsdw:jedw)) ; bt_obc%H_u(:,:) = 0.0
2610  allocate(bt_obc%uhbt(isdw-1:iedw,jsdw:jedw)) ; bt_obc%uhbt(:,:) = 0.0
2611  allocate(bt_obc%ubt_outer(isdw-1:iedw,jsdw:jedw)) ; bt_obc%ubt_outer(:,:) = 0.0
2612  allocate(bt_obc%eta_outer_u(isdw-1:iedw,jsdw:jedw)) ; bt_obc%eta_outer_u(:,:) = 0.0
2613 
2614  allocate(bt_obc%Cg_v(isdw:iedw,jsdw-1:jedw)) ; bt_obc%Cg_v(:,:) = 0.0
2615  allocate(bt_obc%H_v(isdw:iedw,jsdw-1:jedw)) ; bt_obc%H_v(:,:) = 0.0
2616  allocate(bt_obc%vhbt(isdw:iedw,jsdw-1:jedw)) ; bt_obc%vhbt(:,:) = 0.0
2617  allocate(bt_obc%vbt_outer(isdw:iedw,jsdw-1:jedw)) ; bt_obc%vbt_outer(:,:) = 0.0
2618  allocate(bt_obc%eta_outer_v(isdw:iedw,jsdw-1:jedw)) ; bt_obc%eta_outer_v(:,:)=0.0
2619 
2620  if (apply_u_obcs) then
2621  if (obc%specified_u_BCs_exist_globally) then
2622  do n = 1, obc%number_of_segments
2623  segment => obc%segment(n)
2624  if (segment%is_E_or_W .and. segment%specified) then
2625  do k=1,nz ; do j=segment%HI%jsd,segment%HI%jed ; do i=segment%HI%IsdB,segment%HI%IedB
2626  bt_obc%uhbt(i,j) = bt_obc%uhbt(i,j) + segment%normal_trans(i,j,k)
2627  enddo ; enddo ; enddo
2628  endif
2629  enddo
2630  endif
2631  do j=js,je ; do i=is-1,ie ; if (obc%segnum_u(i,j) /= obc_none) then
2632  if (obc%segment(obc%segnum_u(i,j))%specified) then
2633  if (use_bt_cont) then
2634  bt_obc%ubt_outer(i,j) = uhbt_to_ubt(bt_obc%uhbt(i,j),btcl_u(i,j))
2635  else
2636  if (datu(i,j) > 0.0) bt_obc%ubt_outer(i,j) = bt_obc%uhbt(i,j) / datu(i,j)
2637  endif
2638  else
2639  bt_obc%Cg_u(i,j) = sqrt(gv%g_prime(1)*(0.5* &
2640  (g%bathyT(i,j) + g%bathyT(i+1,j))))
2641  if (gv%Boussinesq) then
2642  bt_obc%H_u(i,j) = 0.5*((g%bathyT(i,j) + eta(i,j)) + &
2643  (g%bathyT(i+1,j) + eta(i+1,j)))
2644  else
2645  bt_obc%H_u(i,j) = 0.5*(eta(i,j) + eta(i+1,j))
2646  endif
2647  endif
2648  endif ; enddo ; enddo
2649  if (obc%Flather_u_BCs_exist_globally) then
2650  do n = 1, obc%number_of_segments
2651  segment => obc%segment(n)
2652  if (segment%is_E_or_W .and. segment%Flather) then
2653  do j=segment%HI%jsd,segment%HI%jed ; do i=segment%HI%IsdB,segment%HI%IedB
2654  bt_obc%ubt_outer(i,j) = segment%normal_vel_bt(i,j)
2655  bt_obc%eta_outer_u(i,j) = segment%eta(i,j)
2656  enddo ; enddo
2657  endif
2658  enddo
2659  endif
2660  endif
2661  if (apply_v_obcs) then
2662  if (obc%specified_v_BCs_exist_globally) then
2663  do n = 1, obc%number_of_segments
2664  segment => obc%segment(n)
2665  if (segment%is_N_or_S .and. segment%specified) then
2666  do k=1,nz ; do j=segment%HI%JsdB,segment%HI%JedB ; do i=segment%HI%isd,segment%HI%ied
2667  bt_obc%vhbt(i,j) = bt_obc%vhbt(i,j) + segment%normal_trans(i,j,k)
2668  enddo ; enddo ; enddo
2669  endif
2670  enddo
2671  endif
2672 
2673  do j=js-1,je ; do i=is,ie ; if (obc%segnum_v(i,j) /= obc_none) then
2674  if (obc%segnum_v(i,j) == obc_simple) then
2675  if (use_bt_cont) then
2676  bt_obc%vbt_outer(i,j) = vhbt_to_vbt(bt_obc%vhbt(i,j),btcl_v(i,j))
2677  else
2678  if (datv(i,j) > 0.0) bt_obc%vbt_outer(i,j) = bt_obc%vhbt(i,j) / datv(i,j)
2679  endif
2680  else
2681  bt_obc%Cg_v(i,j) = sqrt(gv%g_prime(1)*(0.5* &
2682  (g%bathyT(i,j) + g%bathyT(i,j+1))))
2683  if (gv%Boussinesq) then
2684  bt_obc%H_v(i,j) = 0.5*((g%bathyT(i,j) + eta(i,j)) + &
2685  (g%bathyT(i,j+1) + eta(i,j+1)))
2686  else
2687  bt_obc%H_v(i,j) = 0.5*(eta(i,j) + eta(i,j+1))
2688  endif
2689  endif
2690  endif ; enddo ; enddo
2691  if (obc%Flather_v_BCs_exist_globally) then
2692  do n = 1, obc%number_of_segments
2693  segment => obc%segment(n)
2694  if (segment%is_N_or_S .and. segment%Flather) then
2695  do j=segment%HI%JsdB,segment%HI%JedB ; do i=segment%HI%isd,segment%HI%ied
2696  bt_obc%vbt_outer(i,j) = segment%normal_vel_bt(i,j)
2697  bt_obc%eta_outer_v(i,j) = segment%eta(i,j)
2698  enddo ; enddo
2699  endif
2700  enddo
2701  endif
2702  endif
2703 end subroutine set_up_bt_obc
2704 
2705 subroutine destroy_bt_obc(BT_OBC)
2706  type(bt_obc_type), intent(inout) :: BT_OBC
2707 
2708  deallocate(bt_obc%Cg_u)
2709  deallocate(bt_obc%H_u)
2710  deallocate(bt_obc%uhbt)
2711  deallocate(bt_obc%ubt_outer)
2712  deallocate(bt_obc%eta_outer_u)
2713 
2714  deallocate(bt_obc%Cg_v)
2715  deallocate(bt_obc%H_v)
2716  deallocate(bt_obc%vhbt)
2717  deallocate(bt_obc%vbt_outer)
2718  deallocate(bt_obc%eta_outer_v)
2719 end subroutine destroy_bt_obc
2720 
2721 !> This subroutine calculates the barotropic velocities from the full velocity and
2722 !! thickness fields, determines the fraction of the total water column in each
2723 !! layer at velocity points, and determines a corrective fictitious mass source
2724 !! that will drive the barotropic estimate of the free surface height toward the
2725 !! baroclinic estimate.
2726 subroutine legacy_btcalc(h, G, GV, CS, h_u, h_v, may_use_default)
2727  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
2728  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid
2729  !! structure.
2730  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses, in H
2731  !! (usually m or kg m-2).
2732  type(legacy_barotropic_cs), pointer :: CS !< The control structure returned
2733  !! by a previous call to barotropic_init.
2734  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
2735  intent(in), optional :: h_u !< The specified thicknesses at u-
2736  !! and v- points, in m or kg m-2.
2737  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), &
2738  intent(in), optional :: h_v !< The specified thicknesses at u-
2739  !! and v- points, in m or kg m-2.
2740  logical, intent(in), optional :: may_use_default
2741 ! btcalc calculates the barotropic velocities from the full velocity and
2742 ! thickness fields, determines the fraction of the total water column in each
2743 ! layer at velocity points, and determines a corrective fictitious mass source
2744 ! that will drive the barotropic estimate of the free surface height toward the
2745 ! baroclinic estimate.
2746 
2747 ! Arguments: h - Layer thickness, in m or kg m-2 (H in later comments).
2748 ! (in) G - The ocean's grid structure.
2749 ! (in) GV - The ocean's vertical grid structure.
2750 ! (in) CS - The control structure returned by a previous call to
2751 ! barotropic_init.
2752 ! (in,opt) h_u, h_v - The specified thicknesses at u- and v- points, in m or kg m-2.
2753 
2754 ! All of these variables are in the same units as h - usually m or kg m-2.
2755  real :: hatutot(szib_(g)) ! The sum of the layer thicknesses
2756  real :: hatvtot(szi_(g)) ! interpolated to the u & v grid points.
2757  real :: Ihatutot(szib_(g)) ! Ihatutot and Ihatvtot are the inverses
2758  real :: Ihatvtot(szi_(g)) ! of hatutot and hatvtot, both in H-1.
2759  real :: h_arith ! The arithmetic mean thickness, in H.
2760  real :: h_harm ! The harmonic mean thicknesses, in H.
2761  real :: h_neglect ! A thickness that is so small it is usually lost
2762  ! in roundoff and can be neglected, in H.
2763  real :: wt_arith ! The nondimensional weight for the arithmetic
2764  ! mean thickness. The harmonic mean uses
2765  ! a weight of (1 - wt_arith).
2766  real :: Rh ! A ratio of summed thicknesses, nondim.
2767  real :: htot(szi_(g),szj_(g)) ! The sum of the layer thicknesses, in H.
2768  real :: e_u(szib_(g),szk_(g)+1) ! The interface heights at u-velocity and
2769  real :: e_v(szi_(g),szk_(g)+1) ! v-velocity points in H.
2770  real :: D_shallow_u(szi_(g)) ! The shallower of the adjacent depths in H.
2771  real :: D_shallow_v(szib_(g))! The shallower of the adjacent depths in H.
2772 
2773  logical :: use_default, test_dflt
2774  integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz, i, j, k
2775 
2776 ! This section interpolates thicknesses onto u & v grid points with the
2777 ! second order accurate estimate h = 2*(h+ * h-)/(h+ + h-).
2778  if (.not.associated(cs)) call mom_error(fatal, &
2779  "legacy_btcalc: Module MOM_legacy_barotropic must be initialized before it is used.")
2780  if (.not.cs%split) return
2781 
2782  use_default = .false.
2783  test_dflt = .false. ; if (present(may_use_default)) test_dflt = may_use_default
2784 
2785  if (test_dflt) then
2786  if (.not.((present(h_u) .and. present(h_v)) .or. &
2787  (cs%hvel_scheme == harmonic) .or. (cs%hvel_scheme == hybrid) .or.&
2788  (cs%hvel_scheme == arithmetic))) use_default = .true.
2789  else
2790  if (.not.((present(h_u) .and. present(h_v)) .or. &
2791  (cs%hvel_scheme == harmonic) .or. (cs%hvel_scheme == hybrid) .or.&
2792  (cs%hvel_scheme == arithmetic))) call mom_error(fatal, &
2793  "legacy_btcalc: Inconsistent settings of optional arguments and hvel_scheme.")
2794  endif
2795 
2796  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
2797  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
2798  h_neglect = gv%H_subroundoff
2799 
2800  ! This estimates the fractional thickness of each layer at the velocity
2801  ! points, using a harmonic mean estimate.
2802 !$OMP parallel do default(none) shared(is,ie,js,je,nz,h_u,CS,h_neglect,h,use_default,G,GV) &
2803 !$OMP private(hatutot,Ihatutot,e_u,D_shallow_u,h_arith,h_harm,wt_arith)
2804  do j=js-1,je+1
2805  if (present(h_u)) then
2806  do i=is-2,ie+1 ; hatutot(i) = h_u(i,j,1) ; enddo
2807  do k=2,nz ; do i=is-2,ie+1
2808  hatutot(i) = hatutot(i) + h_u(i,j,k)
2809  enddo ; enddo
2810  do i=is-2,ie+1 ; ihatutot(i) = 1.0 / (hatutot(i) + h_neglect) ; enddo
2811  do k=1,nz ; do i=is-2,ie+1
2812  cs%frhatu(i,j,k) = h_u(i,j,k) * ihatutot(i)
2813  enddo ; enddo
2814  else
2815  if (cs%hvel_scheme == arithmetic) then
2816  do i=is-2,ie+1
2817  cs%frhatu(i,j,1) = 0.5 * (h(i+1,j,1) + h(i,j,1))
2818  hatutot(i) = cs%frhatu(i,j,1)
2819  enddo
2820  do k=2,nz ; do i=is-2,ie+1
2821  cs%frhatu(i,j,k) = 0.5 * (h(i+1,j,k) + h(i,j,k))
2822  hatutot(i) = hatutot(i) + cs%frhatu(i,j,k)
2823  enddo ; enddo
2824  elseif (cs%hvel_scheme == hybrid .or. use_default) then
2825  do i=is-2,ie+1
2826  e_u(i,nz+1) = -0.5 * gv%m_to_H * (g%bathyT(i+1,j) + g%bathyT(i,j))
2827  d_shallow_u(i) = -gv%m_to_H * min(g%bathyT(i+1,j), g%bathyT(i,j))
2828  hatutot(i) = 0.0
2829  enddo
2830  do k=nz,1,-1 ; do i=is-2,ie+1
2831  e_u(i,k) = e_u(i,k+1) + 0.5 * (h(i+1,j,k) + h(i,j,k))
2832  h_arith = 0.5 * (h(i+1,j,k) + h(i,j,k))
2833  if (e_u(i,k+1) >= d_shallow_u(i)) then
2834  cs%frhatu(i,j,k) = h_arith
2835  else
2836  h_harm = (h(i+1,j,k) * h(i,j,k)) / (h_arith + h_neglect)
2837  if (e_u(i,k) <= d_shallow_u(i)) then
2838  cs%frhatu(i,j,k) = h_harm
2839  else
2840  wt_arith = (e_u(i,k) - d_shallow_u(i)) / (h_arith + h_neglect)
2841  cs%frhatu(i,j,k) = wt_arith*h_arith + (1.0-wt_arith)*h_harm
2842  endif
2843  endif
2844  hatutot(i) = hatutot(i) + cs%frhatu(i,j,k)
2845  enddo ; enddo
2846  elseif (cs%hvel_scheme == harmonic) then
2847  do i=is-2,ie+1
2848  cs%frhatu(i,j,1) = 2.0*(h(i+1,j,1) * h(i,j,1)) / &
2849  ((h(i+1,j,1) + h(i,j,1)) + h_neglect)
2850  hatutot(i) = cs%frhatu(i,j,1)
2851  enddo
2852  do k=2,nz ; do i=is-2,ie+1
2853  cs%frhatu(i,j,k) = 2.0*(h(i+1,j,k) * h(i,j,k)) / &
2854  ((h(i+1,j,k) + h(i,j,k)) + h_neglect)
2855  hatutot(i) = hatutot(i) + cs%frhatu(i,j,k)
2856  enddo ; enddo
2857  endif
2858  do i=is-2,ie+1 ; ihatutot(i) = 1.0 / (hatutot(i) + h_neglect) ; enddo
2859  do k=1,nz ; do i=is-2,ie+1
2860  cs%frhatu(i,j,k) = cs%frhatu(i,j,k) * ihatutot(i)
2861  enddo ; enddo
2862  endif
2863  enddo
2864 
2865 !$OMP parallel do default(none) shared(is,ie,js,je,nz,CS,G,GV,h_v,h_neglect,h,use_default) &
2866 !$OMP private(hatvtot,Ihatvtot,e_v,D_shallow_v,h_arith,h_harm,wt_arith)
2867  do j=js-2,je+1
2868  if (present(h_v)) then
2869  do i=is-1,ie+1 ; hatvtot(i) = h_v(i,j,1) ; enddo
2870  do k=2,nz ; do i=is-1,ie+1
2871  hatvtot(i) = hatvtot(i) + h_v(i,j,k)
2872  enddo ; enddo
2873  do i=is-1,ie+1 ; ihatvtot(i) = 1.0 / (hatvtot(i) + h_neglect) ; enddo
2874  do k=1,nz ; do i=is-1,ie+1
2875  cs%frhatv(i,j,k) = h_v(i,j,k) * ihatvtot(i)
2876  enddo ; enddo
2877  else
2878  if (cs%hvel_scheme == arithmetic) then
2879  do i=is-1,ie+1
2880  cs%frhatv(i,j,1) = 0.5 * (h(i,j+1,1) + h(i,j,1))
2881  hatvtot(i) = cs%frhatv(i,j,1)
2882  enddo
2883  do k=2,nz ; do i=is-1,ie+1
2884  cs%frhatv(i,j,k) = 0.5 * (h(i,j+1,k) + h(i,j,k))
2885  hatvtot(i) = hatvtot(i) + cs%frhatv(i,j,k)
2886  enddo ; enddo
2887  elseif (cs%hvel_scheme == hybrid .or. use_default) then
2888  do i=is-1,ie+1
2889  e_v(i,nz+1) = -0.5 * gv%m_to_H * (g%bathyT(i,j+1) + g%bathyT(i,j))
2890  d_shallow_v(i) = -gv%m_to_H * min(g%bathyT(i,j+1), g%bathyT(i,j))
2891  hatvtot(i) = 0.0
2892  enddo
2893  do k=nz,1,-1 ; do i=is-1,ie+1
2894  e_v(i,k) = e_v(i,k+1) + 0.5 * (h(i,j+1,k) + h(i,j,k))
2895  h_arith = 0.5 * (h(i,j+1,k) + h(i,j,k))
2896  if (e_v(i,k+1) >= d_shallow_v(i)) then
2897  cs%frhatv(i,j,k) = h_arith
2898  else
2899  h_harm = (h(i,j+1,k) * h(i,j,k)) / (h_arith + h_neglect)
2900  if (e_v(i,k) <= d_shallow_v(i)) then
2901  cs%frhatv(i,j,k) = h_harm
2902  else
2903  wt_arith = (e_v(i,k) - d_shallow_v(i)) / (h_arith + h_neglect)
2904  cs%frhatv(i,j,k) = wt_arith*h_arith + (1.0-wt_arith)*h_harm
2905  endif
2906  endif
2907  hatvtot(i) = hatvtot(i) + cs%frhatv(i,j,k)
2908  enddo ; enddo
2909  elseif (cs%hvel_scheme == harmonic) then
2910  do i=is-1,ie+1
2911  cs%frhatv(i,j,1) = 2.0*(h(i,j+1,1) * h(i,j,1)) / &
2912  ((h(i,j+1,1) + h(i,j,1)) + h_neglect)
2913  hatvtot(i) = cs%frhatv(i,j,1)
2914  enddo
2915  do k=2,nz ; do i=is-1,ie+1
2916  cs%frhatv(i,j,k) = 2.0*(h(i,j+1,k) * h(i,j,k)) / &
2917  ((h(i,j+1,k) + h(i,j,k)) + h_neglect)
2918  hatvtot(i) = hatvtot(i) + cs%frhatv(i,j,k)
2919  enddo ; enddo
2920  endif
2921  do i=is-1,ie+1 ; ihatvtot(i) = 1.0 / (hatvtot(i) + h_neglect) ; enddo
2922  do k=1,nz ; do i=is-1,ie+1
2923  cs%frhatv(i,j,k) = cs%frhatv(i,j,k) * ihatvtot(i)
2924  enddo ; enddo
2925  endif
2926  enddo
2927 
2928  if (cs%rescale_D_bt) then
2929  do j=js-2,je+2 ; do i=is-2,ie+2 ; htot(i,j) = 0.0 ; enddo ; enddo
2930  do k=1,nz ; do j=js-2,je+2 ; do i=is-2,ie+2
2931  htot(i,j) = htot(i,j) + h(i,j,k)
2932  enddo ; enddo ; enddo
2933 
2934 !$OMP parallel do default(none) shared(is,ie,js,je,nz,h,htot,h_neglect,CS) &
2935 !$OMP private(hatutot, h_harm, Rh)
2936  do j=js-1,je+1
2937  do i=is-2,ie+1 ; hatutot(i) = 0.0 ; enddo
2938  do k=1,nz ; do i=is-2,ie+1
2939  h_harm = 2.0*(h(i+1,j,k) * h(i,j,k)) / &
2940  ((h(i+1,j,k) + h(i,j,k)) + h_neglect)
2941  hatutot(i) = hatutot(i) + h_harm
2942  enddo ; enddo
2943  do i=is-2,ie+1
2944  rh = hatutot(i) * (htot(i+1,j) + htot(i,j)) / &
2945  (2.0*(htot(i+1,j) * htot(i,j) + h_neglect**2))
2946  cs%Datu_res(i,j) = 1.0
2947  ! This curve satisfies F(1/2) = 1; F'(1/2) = 0; F(x) ~ x for x<<1.
2948  if (rh < 0.5) cs%Datu_res(i,j) = rh * ((4.0-7.0*rh) / (2.0-3.0*rh)**2)
2949  enddo
2950  enddo
2951 
2952 !$OMP parallel do default(none) shared(is,ie,js,je,nz,h,htot,h_neglect,CS) &
2953 !$OMP private(hatvtot, h_harm, Rh)
2954  do j=js-2,je+1
2955  do i=is-1,ie+1 ; hatvtot(i) = 0.0 ; enddo
2956  do k=1,nz ; do i=is-1,ie+1
2957  h_harm = 2.0*(h(i,j+1,k) * h(i,j,k)) / &
2958  ((h(i,j+1,k) + h(i,j,k)) + h_neglect)
2959  hatvtot(i) = hatvtot(i) + h_harm
2960  enddo ; enddo
2961  do i=is-1,ie+1
2962  rh = hatvtot(i) * (htot(i,j+1) + htot(i,j)) / &
2963  (2.0*(htot(i,j+1) * htot(i,j) + h_neglect**2))
2964  cs%Datv_res(i,j) = 1.0
2965  ! This curve satisfies F(1/2) = 1; F'(1/2) = 0; F(x) ~ x for x<<1.
2966  if (rh < 0.5) cs%Datv_res(i,j) = rh * ((4.0-7.0*rh) / (2.0-3.0*rh)**2)
2967  enddo
2968  enddo
2969  endif
2970 
2971  if (cs%debug) then
2972  call uvchksum("btcalc frhat[uv]", cs%frhatu, cs%frhatv, g%HI, haloshift=1)
2973  call hchksum(h, "btcalc h", g%HI, haloshift=1, scale=gv%H_to_m)
2974  endif
2975 
2976 end subroutine legacy_btcalc
2977 
2978 function find_uhbt(u, BTC) result(uhbt)
2979  real, intent(in) :: u !< The zonal velocity, in m s-1
2980  type(local_bt_cont_u_type), intent(in) :: BTC
2981  real :: uhbt ! The result
2982  ! This function evaluates the zonal transport function.
2983 
2984  if (u == 0.0) then
2985  uhbt = 0.0
2986  elseif (u < btc%uBT_EE) then
2987  uhbt = (u - btc%uBT_EE) * btc%FA_u_EE + btc%uh_EE
2988  elseif (u < 0.0) then
2989  uhbt = u * (btc%FA_u_E0 + btc%uh_crvE * u**2)
2990  elseif (u <= btc%uBT_WW) then
2991  uhbt = u * (btc%FA_u_W0 + btc%uh_crvW * u**2)
2992  else ! (u > BTC%uBT_WW)
2993  uhbt = (u - btc%uBT_WW) * btc%FA_u_WW + btc%uh_WW
2994  endif
2995 end function find_uhbt
2996 
2997 function uhbt_to_ubt(uhbt, BTC, guess) result(ubt)
2998  real, intent(in) :: uhbt !< The barotropic zonal transport that should be
2999  !! inverted for, in units of H m2 s-1.
3000  type(local_bt_cont_u_type), intent(in) :: BTC !< A structure containing various fields that
3001  !! allow the barotropic transports to be calculated
3002  !! consistently with the layers' continuity equations.
3003  real, optional, intent(in) :: guess !< A guess at what ubt will be. The result is not
3004  !! allowed to be dramatically larger than guess.
3005  real :: ubt !< The result
3006  ! This function inverts the transport function to determine the barotopic
3007  ! velocity that is consistent with a given transport.
3008  ! Arguments: uhbt - The barotropic zonal transport that should be inverted
3009  ! for, in units of H m2 s-1.
3010  ! (in) BTC - A structure containing various fields that allow the
3011  ! barotropic transports to be calculated consistently with
3012  ! the layers' continuity equations.
3013  ! (in,opt) FA_rat_EE - The current value of the far-east face area divided
3014  ! by its value when uhbt was originally calculated, ND.
3015  ! (in,opt) FA_rat_WW - The current value of the far-west face area divided
3016  ! by its value when uhbt was originally calculated, ND.
3017  ! (in, opt) guess - A guess at what ubt will be. The result is not allowed
3018  ! to be dramatically larger than guess.
3019  ! result: ubt - The velocity that gives uhbt transport, in m s-1.
3020  real :: ubt_min, ubt_max, uhbt_err, derr_du
3021  real :: uherr_min, uherr_max
3022  real, parameter :: tol = 1.0e-10
3023  real :: dvel, vsr ! Temporary variables used in the limiting the velocity.
3024  real, parameter :: vs1 = 1.25 ! Nondimensional parameters used in limiting
3025  real, parameter :: vs2 = 2.0 ! the velocity, starting at vs1, with the
3026  ! maximum increase of vs2, both nondim.
3027  integer :: itt, max_itt = 20
3028 
3029  ! Find the value of ubt that gives uhbt.
3030  if (uhbt == 0.0) then
3031  ubt = 0.0
3032  elseif (uhbt < btc%uh_EE) then
3033  ubt = btc%uBT_EE + (uhbt - btc%uh_EE) / btc%FA_u_EE
3034  elseif (uhbt < 0.0) then
3035  ! Iterate to convergence with Newton's method (when bounded) and the
3036  ! false position method otherwise. ubt will be negative.
3037  ubt_min = btc%uBT_EE ; uherr_min = btc%uh_EE - uhbt
3038  ubt_max = 0.0 ; uherr_max = -uhbt
3039  ! Use a false-position method first guess.
3040  ubt = btc%uBT_EE * (uhbt / btc%uh_EE)
3041  do itt = 1, max_itt
3042  uhbt_err = ubt * (btc%FA_u_E0 + btc%uh_crvE * ubt**2) - uhbt
3043 
3044  if (abs(uhbt_err) < tol*abs(uhbt)) exit
3045  if (uhbt_err > 0.0) then ; ubt_max = ubt ; uherr_max = uhbt_err ; endif
3046  if (uhbt_err < 0.0) then ; ubt_min = ubt ; uherr_min = uhbt_err ; endif
3047 
3048  derr_du = btc%FA_u_E0 + 3.0 * btc%uh_crvE * ubt**2
3049  if ((uhbt_err >= derr_du*(ubt - ubt_min)) .or. &
3050  (-uhbt_err >= derr_du*(ubt_max - ubt)) .or. (derr_du <= 0.0)) then
3051  ! Use a false-position method guess.
3052  ubt = ubt_max + (ubt_min-ubt_max) * (uherr_max / (uherr_max-uherr_min))
3053  else ! Use Newton's method.
3054  ubt = ubt - uhbt_err / derr_du
3055  if (abs(uhbt_err) < (0.01*tol)*abs(ubt_min*derr_du)) exit
3056  endif
3057  enddo
3058  elseif (uhbt <= btc%uh_WW) then
3059  ! Iterate to convergence with Newton's method. ubt will be positive.
3060  ubt_min = 0.0 ; uherr_min = -uhbt
3061  ubt_max = btc%uBT_WW ; uherr_max = btc%uh_WW - uhbt
3062  ! Use a false-position method first guess.
3063  ubt = btc%uBT_WW * (uhbt / btc%uh_WW)
3064  do itt = 1, max_itt
3065  uhbt_err = ubt * (btc%FA_u_W0 + btc%uh_crvW * ubt**2) - uhbt
3066 
3067  if (abs(uhbt_err) < tol*abs(uhbt)) exit
3068  if (uhbt_err > 0.0) then ; ubt_max = ubt ; uherr_max = uhbt_err ; endif
3069  if (uhbt_err < 0.0) then ; ubt_min = ubt ; uherr_min = uhbt_err ; endif
3070 
3071  derr_du = btc%FA_u_W0 + 3.0 * btc%uh_crvW * ubt**2
3072  if ((uhbt_err >= derr_du*(ubt - ubt_min)) .or. &
3073  (-uhbt_err >= derr_du*(ubt_max - ubt)) .or. (derr_du <= 0.0)) then
3074  ! Use a false-position method guess.
3075  ubt = ubt_min + (ubt_max-ubt_min) * (-uherr_min / (uherr_max-uherr_min))
3076  else ! Use Newton's method.
3077  ubt = ubt - uhbt_err / derr_du
3078  if (abs(uhbt_err) < (0.01*tol)*(ubt_max*derr_du)) exit
3079  endif
3080  enddo
3081  else ! (uhbt > BTC%uh_WW)
3082  ubt = btc%uBT_WW + (uhbt - btc%uh_WW) / btc%FA_u_WW
3083  endif
3084 
3085  if (present(guess)) then
3086  dvel = abs(ubt) - vs1*abs(guess)
3087  if (dvel > 0.0) then ! Limit the velocity
3088  if (dvel < 40.0 * (abs(guess)*(vs2-vs1)) ) then
3089  vsr = vs2 - (vs2-vs1) * exp(-dvel / (abs(guess)*(vs2-vs1)))
3090  else ! The exp be less than 4e-18 anyway in this case, so neglect it.
3091  vsr = vs2
3092  endif
3093  ubt = sign(vsr * guess, ubt)
3094  endif
3095  endif
3096 
3097 end function uhbt_to_ubt
3098 
3099 function find_vhbt(v, BTC) result(vhbt)
3100  real, intent(in) :: v !< The meridional velocity, in m s-1
3101  type(local_bt_cont_v_type), intent(in) :: BTC
3102  real :: vhbt ! The result
3103  ! This function evaluates the meridional transport function.
3104 
3105  if (v == 0.0) then
3106  vhbt = 0.0
3107  elseif (v < btc%vBT_NN) then
3108  vhbt = (v - btc%vBT_NN) * btc%FA_v_NN + btc%vh_NN
3109  elseif (v < 0.0) then
3110  vhbt = v * (btc%FA_v_N0 + btc%vh_crvN * v**2)
3111  elseif (v <= btc%vBT_SS) then
3112  vhbt = v * (btc%FA_v_S0 + btc%vh_crvS * v**2)
3113  else ! (v > BTC%vBT_SS)
3114  vhbt = (v - btc%vBT_SS) * btc%FA_v_SS + btc%vh_SS
3115  endif
3116 end function find_vhbt
3117 
3118 function vhbt_to_vbt(vhbt, BTC, guess) result(vbt)
3119  real, intent(in) :: vhbt
3120  type(local_bt_cont_v_type), intent(in) :: BTC !< A structure containing various fields that
3121  !! allow the barotropic transports to be calculated
3122  !! consistently with the layers' continuity equations.
3123  real, optional, intent(in) :: guess !< A guess at what vbt will be. The result is not
3124  !! allowed to be dramatically larger than guess.
3125  real :: vbt !< The result: The velocity that gives vhbt
3126  !! transport, in m s-1.
3127  ! This function inverts the transport function to determine the barotopic
3128  ! velocity that is consistent with a given transport.
3129  ! Arguments: vhbt_in - The barotropic meridional transport that should be
3130  ! inverted for, in units of H m2 s-1.
3131  ! (in) BTC - A structure containing various fields that allow the
3132  ! barotropic transports to be calculated consistently with
3133  ! the layers' continuity equations.
3134  ! (in,opt) FA_rat_NN - The current value of the far-north face area divided
3135  ! by its value when vhbt was originally calculated, ND.
3136  ! (in,opt) FA_rat_SS - The current value of the far-south face area divided
3137  ! by its value when vhbt was originally calculated, ND.
3138  ! (in, opt) guess - A guess at what vbt will be. The result is not allowed
3139  ! to be dramatically larger than guess.
3140  ! result: vbt - The velocity that gives vhbt transport, in m s-1.
3141  real :: vbt_min, vbt_max, vhbt_err, derr_dv
3142  real :: vherr_min, vherr_max
3143  real, parameter :: tol = 1.0e-10
3144  real :: dvel, vsr ! Temporary variables used in the limiting the velocity.
3145  real, parameter :: vs1 = 1.25 ! Nondimensional parameters used in limiting
3146  real, parameter :: vs2 = 2.0 ! the velocity, starting at vs1, with the
3147  ! maximum increase of vs2, both nondim.
3148  integer :: itt, max_itt = 20
3149 
3150  ! Find the value of vbt that gives vhbt.
3151  if (vhbt == 0.0) then
3152  vbt = 0.0
3153  elseif (vhbt < btc%vh_NN) then
3154  vbt = btc%vBT_NN + (vhbt - btc%vh_NN) / btc%FA_v_NN
3155  elseif (vhbt < 0.0) then
3156  ! Iterate to convergence with Newton's method (when bounded) and the
3157  ! false position method otherwise. vbt will be negative.
3158  vbt_min = btc%vBT_NN ; vherr_min = btc%vh_NN - vhbt
3159  vbt_max = 0.0 ; vherr_max = -vhbt
3160  ! Use a false-position method first guess.
3161  vbt = btc%vBT_NN * (vhbt / btc%vh_NN)
3162  do itt = 1, max_itt
3163  vhbt_err = vbt * (btc%FA_v_N0 + btc%vh_crvN * vbt**2) - vhbt
3164 
3165  if (abs(vhbt_err) < tol*abs(vhbt)) exit
3166  if (vhbt_err > 0.0) then ; vbt_max = vbt ; vherr_max = vhbt_err ; endif
3167  if (vhbt_err < 0.0) then ; vbt_min = vbt ; vherr_min = vhbt_err ; endif
3168 
3169  derr_dv = btc%FA_v_N0 + 3.0 * btc%vh_crvN * vbt**2
3170  if ((vhbt_err >= derr_dv*(vbt - vbt_min)) .or. &
3171  (-vhbt_err >= derr_dv*(vbt_max - vbt)) .or. (derr_dv <= 0.0)) then
3172  ! Use a false-position method guess.
3173  vbt = vbt_max + (vbt_min-vbt_max) * (vherr_max / (vherr_max-vherr_min))
3174  else ! Use Newton's method.
3175  vbt = vbt - vhbt_err / derr_dv
3176  if (abs(vhbt_err) < (0.01*tol)*abs(derr_dv*vbt_min)) exit
3177  endif
3178  enddo
3179  elseif (vhbt <= btc%vh_SS) then
3180  ! Iterate to convergence with Newton's method. vbt will be positive.
3181  vbt_min = 0.0 ; vherr_min = -vhbt
3182  vbt_max = btc%vBT_SS ; vherr_max = btc%vh_SS - vhbt
3183  ! Use a false-position method first guess.
3184  vbt = btc%vBT_SS * (vhbt / btc%vh_SS)
3185  do itt = 1, max_itt
3186  vhbt_err = vbt * (btc%FA_v_S0 + btc%vh_crvS * vbt**2) - vhbt
3187 
3188  if (abs(vhbt_err) < tol*abs(vhbt)) exit
3189  if (vhbt_err > 0.0) then ; vbt_max = vbt ; vherr_max = vhbt_err ; endif
3190  if (vhbt_err < 0.0) then ; vbt_min = vbt ; vherr_min = vhbt_err ; endif
3191 
3192  derr_dv = btc%FA_v_S0 + 3.0 * btc%vh_crvS * vbt**2
3193  if ((vhbt_err >= derr_dv*(vbt - vbt_min)) .or. &
3194  (-vhbt_err >= derr_dv*(vbt_max - vbt)) .or. (derr_dv <= 0.0)) then
3195  ! Use a false-position method guess.
3196  vbt = vbt_min + (vbt_max-vbt_min) * (-vherr_min / (vherr_max-vherr_min))
3197  else ! Use Newton's method.
3198  vbt = vbt - vhbt_err / derr_dv
3199  if (abs(vhbt_err) < (0.01*tol)*(vbt_max*derr_dv)) exit
3200  endif
3201  enddo
3202  else ! (vhbt > BTC%vh_SS)
3203  vbt = btc%vBT_SS + (vhbt - btc%vh_SS) / btc%FA_v_SS
3204  endif
3205 
3206  if (present(guess)) then
3207  dvel = abs(vbt) - vs1*abs(guess)
3208  if (dvel > 0.0) then ! Limit the velocity
3209  if (dvel < 40.0 * (abs(guess)*(vs2-vs1)) ) then
3210  vsr = vs2 - (vs2-vs1) * exp(-dvel / (abs(guess)*(vs2-vs1)))
3211  else ! The exp be less than 4e-18 anyway in this case, so neglect it.
3212  vsr = vs2
3213  endif
3214  vbt = sign(guess * vsr, vbt)
3215  endif
3216  endif
3217 
3218 end function vhbt_to_vbt
3219 
3220 
3221 subroutine set_local_bt_cont_types(BT_cont, BTCL_u, BTCL_v, G, MS, BT_Domain, halo)
3222  type(bt_cont_type), intent(inout) :: BT_cont !< The BT_cont_type input to the
3223  !! barotropic solver.
3224  type(memory_size_type), intent(in) :: MS !< A type that describes the
3225  !! memory sizes of the argument arrays.
3226  type(local_bt_cont_u_type), dimension(SZIBW_(MS),SZJW_(MS)), &
3227  intent(out) :: BTCL_u !< A structure with the u
3228  !! information from BT_cont.
3229  type(local_bt_cont_v_type), dimension(SZIW_(MS),SZJBW_(MS)), &
3230  intent(out) :: BTCL_v !< A structure with the v
3231  !! information from BT_cont.
3232  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
3233  type(mom_domain_type), intent(inout) :: BT_Domain !< The domain to use for
3234  !! updating the halos of wide arrays.
3235  integer, optional, intent(in) :: halo !< The extra halo size
3236  !! to use here.
3237 ! This subroutine sets up reordered versions of the BT_cont type in the
3238 ! local_BT_cont types, which have wide halos properly filled in.
3239 ! Arguments: BT_cont - The BT_cont_type input to the barotropic solver.
3240 ! (out) BTCL_u - A structure with the u information from BT_cont.
3241 ! (out) BTCL_v - A structure with the v information from BT_cont.
3242 ! (in) G - The ocean's grid structure.
3243 ! (in) MS - A type that describes the memory sizes of the argument arrays.
3244 ! (in) BT_Domain - The domain to use for updating the halos of wide arrays.
3245 ! (in) halo - The extra halo size to use here.
3246 
3247  real, dimension(SZIBW_(MS),SZJW_(MS)) :: &
3248  u_polarity, uBT_EE, uBT_WW, FA_u_EE, FA_u_E0, FA_u_W0, FA_u_WW
3249  real, dimension(SZIW_(MS),SZJBW_(MS)) :: &
3250  v_polarity, vBT_NN, vBT_SS, FA_v_NN, FA_v_N0, FA_v_S0, FA_v_SS
3251  real, parameter :: C1_3 = 1.0/3.0
3252  integer :: i, j, is, ie, js, je, hs
3253  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
3254  hs = 1 ; if (present(halo)) hs = max(halo,0)
3255 
3256  ! Copy the BT_cont arrays into symmetric, potentially wide haloed arrays.
3257  u_polarity(:,:) = 1.0
3258  ubt_ee(:,:) = 0.0 ; ubt_ww(:,:) = 0.0
3259  fa_u_ee(:,:) = 0.0 ; fa_u_e0(:,:) = 0.0 ; fa_u_w0(:,:) = 0.0 ; fa_u_ww(:,:) = 0.0
3260  do i=is-1,ie ; do j=js,je
3261  ubt_ee(i,j) = bt_cont%uBT_EE(i,j) ; ubt_ww(i,j) = bt_cont%uBT_WW(i,j)
3262  fa_u_ee(i,j) = bt_cont%FA_u_EE(i,j) ; fa_u_e0(i,j) = bt_cont%FA_u_E0(i,j)
3263  fa_u_w0(i,j) = bt_cont%FA_u_W0(i,j) ; fa_u_ww(i,j) = bt_cont%FA_u_WW(i,j)
3264  enddo ; enddo
3265 
3266  v_polarity(:,:) = 1.0
3267  vbt_nn(:,:) = 0.0 ; vbt_ss(:,:) = 0.0
3268  fa_v_nn(:,:) = 0.0 ; fa_v_n0(:,:) = 0.0 ; fa_v_s0(:,:) = 0.0 ; fa_v_ss(:,:) = 0.0
3269  do i=is,ie ; do j=js-1,je
3270  vbt_nn(i,j) = bt_cont%vBT_NN(i,j) ; vbt_ss(i,j) = bt_cont%vBT_SS(i,j)
3271  fa_v_nn(i,j) = bt_cont%FA_v_NN(i,j) ; fa_v_n0(i,j) = bt_cont%FA_v_N0(i,j)
3272  fa_v_s0(i,j) = bt_cont%FA_v_S0(i,j) ; fa_v_ss(i,j) = bt_cont%FA_v_SS(i,j)
3273  enddo ; enddo
3274 
3275  if (id_clock_calc_pre > 0) call cpu_clock_end(id_clock_calc_pre)
3276  if (id_clock_pass_pre > 0) call cpu_clock_begin(id_clock_pass_pre)
3277  ! Do halo updates on BT_cont.
3278  call pass_vector(u_polarity, v_polarity, bt_domain, complete=.false.)
3279  call pass_vector(ubt_ee, vbt_nn, bt_domain, complete=.false.)
3280  call pass_vector(ubt_ww, vbt_ss, bt_domain, complete=.true.)
3281 
3282  call pass_vector(fa_u_ee, fa_v_nn, bt_domain, to_all+scalar_pair, complete=.false.)
3283  call pass_vector(fa_u_e0, fa_v_n0, bt_domain, to_all+scalar_pair, complete=.false.)
3284  call pass_vector(fa_u_w0, fa_v_s0, bt_domain, to_all+scalar_pair, complete=.false.)
3285  call pass_vector(fa_u_ww, fa_v_ss, bt_domain, to_all+scalar_pair, complete=.true.)
3286  if (id_clock_pass_pre > 0) call cpu_clock_end(id_clock_pass_pre)
3287  if (id_clock_calc_pre > 0) call cpu_clock_begin(id_clock_calc_pre)
3288 
3289  do j=js-hs,je+hs ; do i=is-hs-1,ie+hs
3290  btcl_u(i,j)%FA_u_EE = fa_u_ee(i,j) ; btcl_u(i,j)%FA_u_E0 = fa_u_e0(i,j)
3291  btcl_u(i,j)%FA_u_W0 = fa_u_w0(i,j) ; btcl_u(i,j)%FA_u_WW = fa_u_ww(i,j)
3292  btcl_u(i,j)%uBT_EE = ubt_ee(i,j) ; btcl_u(i,j)%uBT_WW = ubt_ww(i,j)
3293  ! Check for reversed polarity in the tripolar halo regions.
3294  if (u_polarity(i,j) < 0.0) then
3295  call swap(btcl_u(i,j)%FA_u_EE, btcl_u(i,j)%FA_u_WW)
3296  call swap(btcl_u(i,j)%FA_u_E0, btcl_u(i,j)%FA_u_W0)
3297  call swap(btcl_u(i,j)%uBT_EE, btcl_u(i,j)%uBT_WW)
3298  endif
3299 
3300  btcl_u(i,j)%uh_EE = btcl_u(i,j)%uBT_EE * &
3301  (c1_3 * (2.0*btcl_u(i,j)%FA_u_E0 + btcl_u(i,j)%FA_u_EE))
3302  btcl_u(i,j)%uh_WW = btcl_u(i,j)%uBT_WW * &
3303  (c1_3 * (2.0*btcl_u(i,j)%FA_u_W0 + btcl_u(i,j)%FA_u_WW))
3304 
3305  btcl_u(i,j)%uh_crvE = 0.0 ; btcl_u(i,j)%uh_crvW = 0.0
3306  if (abs(btcl_u(i,j)%uBT_WW) > 0.0) btcl_u(i,j)%uh_crvW = &
3307  (c1_3 * (btcl_u(i,j)%FA_u_WW - btcl_u(i,j)%FA_u_W0)) / btcl_u(i,j)%uBT_WW**2
3308  if (abs(btcl_u(i,j)%uBT_EE) > 0.0) btcl_u(i,j)%uh_crvE = &
3309  (c1_3 * (btcl_u(i,j)%FA_u_EE - btcl_u(i,j)%FA_u_E0)) / btcl_u(i,j)%uBT_EE**2
3310  enddo ; enddo
3311 
3312  do j=js-hs-1,je+hs ; do i=is-hs,ie+hs
3313  btcl_v(i,j)%FA_v_NN = fa_v_nn(i,j) ; btcl_v(i,j)%FA_v_N0 = fa_v_n0(i,j)
3314  btcl_v(i,j)%FA_v_S0 = fa_v_s0(i,j) ; btcl_v(i,j)%FA_v_SS = fa_v_ss(i,j)
3315  btcl_v(i,j)%vBT_NN = vbt_nn(i,j) ; btcl_v(i,j)%vBT_SS = vbt_ss(i,j)
3316  ! Check for reversed polarity in the tripolar halo regions.
3317  if (v_polarity(i,j) < 0.0) then
3318  call swap(btcl_v(i,j)%FA_v_NN, btcl_v(i,j)%FA_v_SS)
3319  call swap(btcl_v(i,j)%FA_v_N0, btcl_v(i,j)%FA_v_S0)
3320  call swap(btcl_v(i,j)%vBT_NN, btcl_v(i,j)%vBT_SS)
3321  endif
3322 
3323  btcl_v(i,j)%vh_NN = btcl_v(i,j)%vBT_NN * &
3324  (c1_3 * (2.0*btcl_v(i,j)%FA_v_N0 + btcl_v(i,j)%FA_v_NN))
3325  btcl_v(i,j)%vh_SS = btcl_v(i,j)%vBT_SS * &
3326  (c1_3 * (2.0*btcl_v(i,j)%FA_v_S0 + btcl_v(i,j)%FA_v_SS))
3327 
3328  btcl_v(i,j)%vh_crvN = 0.0 ; btcl_v(i,j)%vh_crvS = 0.0
3329  if (abs(btcl_v(i,j)%vBT_SS) > 0.0) btcl_v(i,j)%vh_crvS = &
3330  (c1_3 * (btcl_v(i,j)%FA_v_SS - btcl_v(i,j)%FA_v_S0)) / btcl_v(i,j)%vBT_SS**2
3331  if (abs(btcl_v(i,j)%vBT_NN) > 0.0) btcl_v(i,j)%vh_crvN = &
3332  (c1_3 * (btcl_v(i,j)%FA_v_NN - btcl_v(i,j)%FA_v_N0)) / btcl_v(i,j)%vBT_NN**2
3333  enddo ; enddo
3334 
3335 end subroutine set_local_bt_cont_types
3336 
3337 subroutine bt_cont_to_face_areas(BT_cont, Datu, Datv, G, MS, halo, maximize)
3338  type(bt_cont_type), intent(inout) :: BT_cont
3339  type(memory_size_type), intent(in) :: MS !< A type that describes the
3340  !! memory sizes of the argument
3341  !! arrays.
3342  real, dimension(MS%isdw-1:MS%iedw,MS%jsdw:MS%jedw), &
3343  intent(out) :: Datu !< The open zonal face area, in
3344  !! H m (m2 or kg m-1).
3345  real, dimension(MS%isdw:MS%iedw,MS%jsdw-1:MS%jedw), &
3346  intent(out) :: Datv !< The open meridional face
3347  !! area, in H m (m2 or kg m-1).
3348  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
3349  integer, optional, intent(in) :: halo !< The halo size to use,
3350  !! default = 1.
3351  logical, optional, intent(in) :: maximize
3352  ! This subroutine uses the BTCL types to find typical or maximum face
3353  ! areas, which can then be used for finding wave speeds, etc.
3354  logical :: find_max
3355  integer :: i, j, is, ie, js, je, hs
3356  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
3357  hs = 1 ; if (present(halo)) hs = max(halo,0)
3358  find_max = .false. ; if (present(maximize)) find_max = maximize
3359 
3360  if (find_max) then
3361  do j=js-hs,je+hs ; do i=is-1-hs,ie+hs
3362  datu(i,j) = max(bt_cont%FA_u_EE(i,j), bt_cont%FA_u_E0(i,j), &
3363  bt_cont%FA_u_W0(i,j), bt_cont%FA_u_WW(i,j))
3364  enddo ; enddo
3365  do j=js-1-hs,je+hs ; do i=is-hs,ie+hs
3366  datv(i,j) = max(bt_cont%FA_v_NN(i,j), bt_cont%FA_v_N0(i,j), &
3367  bt_cont%FA_v_S0(i,j), bt_cont%FA_v_SS(i,j))
3368  enddo ; enddo
3369  else
3370  do j=js-hs,je+hs ; do i=is-1-hs,ie+hs
3371  datu(i,j) = 0.5 * (bt_cont%FA_u_E0(i,j) + bt_cont%FA_u_W0(i,j))
3372  enddo ; enddo
3373  do j=js-1-hs,je+hs ; do i=is-hs,ie+hs
3374  datv(i,j) = 0.5 * (bt_cont%FA_v_N0(i,j) + bt_cont%FA_v_S0(i,j))
3375  enddo ; enddo
3376  endif
3377 end subroutine bt_cont_to_face_areas
3378 
3379 subroutine swap(a,b)
3380  real, intent(inout) :: a, b
3381  real :: tmp
3382  tmp = a ; a = b ; b = tmp
3383 end subroutine swap
3384 
3385 subroutine find_face_areas(Datu, Datv, G, GV, CS, MS, rescale_faces, eta, halo, add_max)
3386  type(memory_size_type), intent(in) :: MS !< A type that describes the memory sizes
3387  !! of the argument arrays.
3388  real, dimension(MS%isdw-1:MS%iedw,MS%jsdw:MS%jedw), &
3389  intent(out) :: Datu !< The open zonal face area, in H m
3390  !! (m2 or kg m-1).
3391  real, dimension(MS%isdw:MS%iedw,MS%jsdw-1:MS%jedw), &
3392  intent(out) :: Datv !< The open meridional face area, in H m
3393  !! (m2 or kg m-1).
3394  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
3395  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
3396  type(legacy_barotropic_cs), pointer :: CS !< The control structure returned by a
3397  !! previous call to barotropic_init.
3398  logical, optional, intent(in) :: rescale_faces !< If true, rescale the face areas
3399  !! by Datu_res, etc.
3400  real, dimension(MS%isdw:MS%iedw,MS%jsdw:MS%jedw), &
3401  optional, intent(in) :: eta !< The barotropic free surface height
3402  !! anomaly or column mass anomaly, in m or kg m-2.
3403  integer, optional, intent(in) :: halo !< The halo size to use, default = 1.
3404  real, optional, intent(in) :: add_max !< A value to add to the maximum depth
3405  !! (used to overestimate the external wave speed) in m.
3406 ! Arguments: Datu - The open zonal face area, in H m (m2 or kg m-1).
3407 ! (out) Datv - The open meridional face area, in H m (m2 or kg m-1).
3408 ! (in) G - The ocean's grid structure.
3409 ! (in) GV - The ocean's vertical grid structure.
3410 ! (in) CS - The control structure returned by a previous call to
3411 ! barotropic_init.
3412 ! (in) MS - A type that describes the memory sizes of the argument arrays.
3413 ! (in, opt) rescale_faces - If true, rescale the face areas by Datu_res, etc.
3414 ! (in, opt) eta - The barotropic free surface height anomaly or
3415 ! column mass anomaly, in m or kg m-2.
3416 ! (in, opt) halo - The halo size to use, default = 1.
3417 ! (in, opt) add_max - A value to add to the maximum depth (used to overestimate
3418 ! the external wave speed) in m.
3419 
3420 
3421 ! This subroutine determines the open face areas of cells for calculating
3422 ! the barotropic transport.
3423  real :: H1, H2 ! Temporary total thicknesses, in m or kg m-2.
3424  logical :: rescale
3425  integer :: i, j, is, ie, js, je, hs
3426  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
3427  hs = 1 ; if (present(halo)) hs = max(halo,0)
3428  rescale = .false. ; if (present(rescale_faces)) rescale = rescale_faces
3429 
3430 !$OMP parallel default(none) shared(is,ie,js,je,hs,eta,GV,CS,Datu,Datv,add_max,rescale) &
3431 !$OMP private(H1,H2)
3432  if (present(eta)) then
3433  ! The use of harmonic mean thicknesses ensure positive definiteness.
3434  if (gv%Boussinesq) then
3435 !$OMP do
3436  do j=js-hs,je+hs ; do i=is-1-hs,ie+hs
3437  h1 = cs%bathyT(i,j) + eta(i,j) ; h2 = cs%bathyT(i+1,j) + eta(i+1,j)
3438  datu(i,j) = 0.0 ; if ((h1 > 0.0) .and. (h2 > 0.0)) &
3439  datu(i,j) = cs%dy_Cu(i,j) * (2.0 * h1 * h2) / (h1 + h2)
3440 ! Datu(I,j) = CS%dy_Cu(I,j) * 0.5 * (H1 + H2)
3441  enddo; enddo
3442 !$OMP do
3443  do j=js-1-hs,je+hs ; do i=is-hs,ie+hs
3444  h1 = cs%bathyT(i,j) + eta(i,j) ; h2 = cs%bathyT(i,j+1) + eta(i,j+1)
3445  datv(i,j) = 0.0 ; if ((h1 > 0.0) .and. (h2 > 0.0)) &
3446  datv(i,j) = cs%dx_Cv(i,j) * (2.0 * h1 * h2) / (h1 + h2)
3447 ! Datv(i,J) = CS%dy_v(i,J) * 0.5 * (H1 + H2)
3448  enddo; enddo
3449  else
3450 !$OMP do
3451  do j=js-hs,je+hs ; do i=is-1-hs,ie+hs
3452  datu(i,j) = 0.0 ; if ((eta(i,j) > 0.0) .and. (eta(i+1,j) > 0.0)) &
3453  datu(i,j) = cs%dy_Cu(i,j) * (2.0 * eta(i,j) * eta(i+1,j)) / &
3454  (eta(i,j) + eta(i+1,j))
3455  ! Datu(I,j) = CS%dy_Cu(I,j) * 0.5 * (eta(i,j) + eta(i+1,j))
3456  enddo; enddo
3457 !$OMP do
3458  do j=js-1-hs,je+hs ; do i=is-hs,ie+hs
3459  datv(i,j) = 0.0 ; if ((eta(i,j) > 0.0) .and. (eta(i,j+1) > 0.0)) &
3460  datv(i,j) = cs%dx_Cv(i,j) * (2.0 * eta(i,j) * eta(i,j+1)) / &
3461  (eta(i,j) + eta(i,j+1))
3462  ! Datv(i,J) = CS%dy_v(i,J) * 0.5 * (eta(i,j) + eta(i,j+1))
3463  enddo; enddo
3464  endif
3465  elseif (present(add_max)) then
3466 !$OMP do
3467  do j=js-hs,je+hs ; do i=is-1-hs,ie+hs
3468  datu(i,j) = cs%dy_Cu(i,j) * gv%m_to_H * &
3469  (max(cs%bathyT(i+1,j), cs%bathyT(i,j)) + add_max)
3470  enddo ; enddo
3471 !$OMP do
3472  do j=js-1-hs,je+hs ; do i=is-hs,ie+hs
3473  datv(i,j) = cs%dx_Cv(i,j) * gv%m_to_H * &
3474  (max(cs%bathyT(i,j+1), cs%bathyT(i,j)) + add_max)
3475  enddo ; enddo
3476  else
3477 !$OMP do
3478  do j=js-hs,je+hs ; do i=is-1-hs,ie+hs
3479  datu(i,j) = 2.0*cs%dy_Cu(i,j) * gv%m_to_H * &
3480  (cs%bathyT(i+1,j) * cs%bathyT(i,j)) / &
3481  (cs%bathyT(i+1,j) + cs%bathyT(i,j))
3482  enddo ; enddo
3483 !$OMP do
3484  do j=js-1-hs,je+hs ; do i=is-hs,ie+hs
3485  datv(i,j) = 2.0*cs%dx_Cv(i,j) * gv%m_to_H * &
3486  (cs%bathyT(i,j+1) * cs%bathyT(i,j)) / &
3487  (cs%bathyT(i,j+1) + cs%bathyT(i,j))
3488  enddo ; enddo
3489  endif
3490 
3491  if (rescale) then
3492 !$OMP do
3493  do j=js-hs,je+hs ; do i=is-1-hs,ie+hs
3494  datu(i,j) = datu(i,j) * cs%Datu_res(i,j)
3495  enddo ; enddo
3496 !$OMP do
3497  do j=js-1-hs,je+hs ; do i=is-hs,ie+hs
3498  datv(i,j) = datv(i,j) * cs%Datv_res(i,j)
3499  enddo ; enddo
3500  endif
3501 !$OMP end parallel
3502 
3503 end subroutine find_face_areas
3504 
3505 subroutine legacy_bt_mass_source(h, eta, fluxes, set_cor, dt_therm, &
3506  dt_since_therm, G, GV, CS)
3507  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
3508  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
3509  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
3510  intent(in) :: h !< Layer thicknesses, in H
3511  !! (usually m or kg m-2).
3512  real, dimension(SZI_(G),SZJ_(G)), &
3513  intent(in) :: eta !< The free surface height that is to be
3514  !! corrected, in m.
3515  type(forcing), intent(in) :: fluxes !< A structure containing pointers to any
3516  !! possible forcing fields. Unused fields
3517  !! have NULL ptrs.
3518  logical, intent(in) :: set_cor !< A flag to indicate whether to set the
3519  !! corrective fluxes (and update the slowly varying part of eta_cor)
3520  !! (.true.) or whether to incrementally update the corrective fluxes.
3521  real, intent(in) :: dt_therm !< The thermodynamic time step, in s.
3522  real, intent(in) :: dt_since_therm !< The elapsed time since mass forcing
3523  !! was applied, s.
3524  type(legacy_barotropic_cs), pointer :: CS !< The control structure returned by a
3525  !! previous call to barotropic_init.
3526 
3527 ! bt_mass_source determines the appropriately limited mass source for
3528 ! the barotropic solver, along with a corrective fictitious mass source that
3529 ! will drive the barotropic estimate of the free surface height toward the
3530 ! baroclinic estimate.
3531 
3532 ! Arguments: h - Layer thickness, in m or kg m-2 (H).
3533 ! (in) eta - The free surface height that is to be corrected, in m.
3534 ! (in) fluxes - A structure containing pointers to any possible
3535 ! forcing fields. Unused fields have NULL ptrs.
3536 ! (in) set_cor - A flag to indicate whether to set the corrective fluxes
3537 ! (and update the slowly varying part of eta_cor) (.true.)
3538 ! or whether to incrementally update the corrective fluxes.
3539 ! (in) dt_therm - The thermodynamic time step, in s.
3540 ! (in) dt_since_therm - The elapsed time since mass forcing was applied, s.
3541 ! (in) G - The ocean's grid structure.
3542 ! (in) GV - The ocean's vertical grid structure.
3543 ! (in) CS - The control structure returned by a previous call to
3544 ! barotropic_init.
3545  real :: h_tot(szi_(g)) ! The sum of the layer thicknesses, in H.
3546  real :: eta_h(szi_(g)) ! The free surface height determined from
3547  ! the sum of the layer thicknesses, in H.
3548  real :: d_eta ! The difference between estimates of the total
3549  ! thicknesses, in H.
3550  real :: limit_dt ! The fractional mass-source limit divided by the
3551  ! thermodynamic time step, in s-1.
3552  integer :: is, ie, js, je, nz, i, j, k
3553  real, parameter :: frac_cor = 0.25
3554  real, parameter :: slow_rate = 0.125
3555 
3556  if (.not.associated(cs)) call mom_error(fatal, "bt_mass_source: "// &
3557  "Module MOM_barotropic must be initialized before it is used.")
3558  if (.not.cs%split) return
3559 
3560  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
3561 
3562 !$OMP parallel do default(none) shared(is,ie,js,je,nz,G,GV,h,set_cor,CS,dt_therm, &
3563 !$OMP fluxes,eta,dt_since_therm) &
3564 !$OMP private(eta_h,h_tot,limit_dt,d_eta)
3565  do j=js,je
3566  do i=is,ie ; h_tot(i) = h(i,j,1) ; enddo
3567  if (gv%Boussinesq) then
3568  do i=is,ie ; eta_h(i) = h(i,j,1) - g%bathyT(i,j) ; enddo
3569  else
3570  do i=is,ie ; eta_h(i) = h(i,j,1) ; enddo
3571  endif
3572  do k=2,nz ; do i=is,ie
3573  eta_h(i) = eta_h(i) + h(i,j,k)
3574  h_tot(i) = h_tot(i) + h(i,j,k)
3575  enddo ; enddo
3576 
3577  if (set_cor) then
3578  do i=is,ie ; cs%eta_source(i,j) = 0.0 ; enddo
3579  if (cs%eta_source_limit > 0.0) then
3580  limit_dt = cs%eta_source_limit/dt_therm
3581  if (associated(fluxes%lprec)) then ; do i=is,ie
3582  cs%eta_source(i,j) = cs%eta_source(i,j) + fluxes%lprec(i,j)
3583  enddo ; endif
3584  if (associated(fluxes%fprec)) then ; do i=is,ie
3585  cs%eta_source(i,j) = cs%eta_source(i,j) + fluxes%fprec(i,j)
3586  enddo ; endif
3587  if (associated(fluxes%vprec)) then ; do i=is,ie
3588  cs%eta_source(i,j) = cs%eta_source(i,j) + fluxes%vprec(i,j)
3589  enddo ; endif
3590  if (associated(fluxes%lrunoff)) then ; do i=is,ie
3591  cs%eta_source(i,j) = cs%eta_source(i,j) + fluxes%lrunoff(i,j)
3592  enddo ; endif
3593  if (associated(fluxes%frunoff)) then ; do i=is,ie
3594  cs%eta_source(i,j) = cs%eta_source(i,j) + fluxes%frunoff(i,j)
3595  enddo ; endif
3596  if (associated(fluxes%evap)) then ; do i=is,ie
3597  cs%eta_source(i,j) = cs%eta_source(i,j) + fluxes%evap(i,j)
3598  enddo ; endif
3599  do i=is,ie
3600  cs%eta_source(i,j) = cs%eta_source(i,j)*gv%kg_m2_to_H
3601  if (abs(cs%eta_source(i,j)) > limit_dt * h_tot(i)) then
3602  cs%eta_source(i,j) = sign(limit_dt * h_tot(i), cs%eta_source(i,j))
3603  endif
3604  enddo
3605  endif
3606  endif
3607 
3608  if (set_cor) then
3609  do i=is,ie
3610  d_eta = eta_h(i) - (eta(i,j) - dt_since_therm*cs%eta_source(i,j))
3611  cs%eta_cor(i,j) = d_eta
3612  enddo
3613  else
3614  do i=is,ie
3615  d_eta = eta_h(i) - (eta(i,j) - dt_since_therm*cs%eta_source(i,j))
3616  cs%eta_cor(i,j) = cs%eta_cor(i,j) + d_eta
3617  enddo
3618  endif
3619  enddo
3620 
3621 end subroutine legacy_bt_mass_source
3622 
3623 subroutine legacy_barotropic_init(u, v, h, eta, Time, G, GV, param_file, diag, CS, &
3624  restart_CS, BT_cont, tides_CSp)
3625  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
3626  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid
3627  !! structure.
3628  real, intent(in), dimension(SZIB_(G),SZJ_(G),SZK_(G)) :: u !< The zonal velocity, in m s-1.
3629  real, intent(in), dimension(SZI_(G),SZJB_(G),SZK_(G)) :: v !< The meridional velocity,
3630  !! in m s-1.
3631  real, intent(in), dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h !< Layer thicknesses, in H
3632  !! (usually m or kg m-2).
3633  real, intent(in), dimension(SZI_(G),SZJ_(G)) :: eta !< Free surface height or column
3634  !! mass anomaly, in m or kg m-2.
3635  type(time_type), target, intent(in) :: Time !< The current model time.
3636  type(param_file_type), intent(in) :: param_file !< A structure to parse for
3637  !! run-time parameters.
3638  type(diag_ctrl), target, intent(inout) :: diag !< A structure that is used to
3639  !! regulate diagnostic output.
3640  type(legacy_barotropic_cs), pointer :: CS !< A pointer to the control
3641  !! structure for this module that is
3642  !! set in register_barotropic_restarts.
3643  type(mom_restart_cs), pointer :: restart_CS !< A pointer to the restart
3644  !! control structure.
3645  type(bt_cont_type), optional, pointer :: BT_cont !< A structure with elements that
3646  !! describe the effective open face areas
3647  !! as a function of barotropic flow.
3648  type(tidal_forcing_cs), optional, pointer :: tides_CSp !< A pointer to the control
3649  !! structure of the tide module.
3650 ! barotropic_init initializes a number of time-invariant fields used in the
3651 ! barotropic calculation and initializes any barotropic fields that have not
3652 ! already been initialized.
3653 
3654 ! Arguments: u - Zonal velocity, in m s-1.
3655 ! (in) v - Meridional velocity, in m s-1.
3656 ! (in) h - Layer thickness, in m or kg m-2.
3657 ! (in) eta - Free surface height or column mass anomaly, in m or kg m-2.
3658 ! (in) Time - The current model time.
3659 ! (in) G - The ocean's grid structure.
3660 ! (in) GV - The ocean's vertical grid structure.
3661 ! (in) param_file - A structure indicating the open file to parse for
3662 ! model parameter values.
3663 ! (in) diag - A structure that is used to regulate diagnostic output.
3664 ! (in/out) CS - A pointer to the control structure for this module that is
3665 ! set in register_barotropic_restarts.
3666 ! (in) restart_CS - A pointer to the restart control structure.
3667 ! (in,opt) BT_cont - A structure with elements that describe the effective
3668 ! open face areas as a function of barotropic flow.
3669 ! (in) tides_CSp - a pointer to the control structure of the tide module.
3670 ! This include declares and sets the variable "version".
3671 #include "version_variable.h"
3672  character(len=40) :: mdl = "MOM_barotropic" ! This module's name.
3673  real :: Datu(szibs_(g),szj_(g)), Datv(szi_(g),szjbs_(g))
3674  real :: gtot_estimate ! Summing GV%g_prime gives an upper-bound estimate for pbce.
3675  real :: SSH_extra ! An estimate of how much higher SSH might get, for use
3676  ! in calculating the safe external wave speed.
3677  real :: dtbt_input
3678  type(memory_size_type) :: MS
3679  logical :: apply_bt_drag, use_BT_cont_type
3680  character(len=48) :: thickness_units, flux_units
3681  character*(40) :: hvel_str
3682  integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
3683  integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB
3684  integer :: isdw, iedw, jsdw, jedw
3685  integer :: i, j, k
3686  integer :: wd_halos(2), bt_halo_sz
3687  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
3688  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
3689  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
3690  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
3691  ms%isdw = g%isd ; ms%iedw = g%ied ; ms%jsdw = g%jsd ; ms%jedw = g%jed
3692 
3693  if (cs%module_is_initialized) then
3694  call mom_error(warning, "barotropic_init called with a control structure "// &
3695  "that has already been initialized.")
3696  return
3697  endif
3698  cs%module_is_initialized = .true.
3699 
3700  cs%diag => diag ; cs%Time => time
3701  if (present(tides_csp)) then
3702  if (associated(tides_csp)) cs%tides_CSp => tides_csp
3703  endif
3704 
3705  ! Read all relevant parameters and write them to the model log.
3706  call log_version(param_file, mdl, version, "")
3707  call get_param(param_file, mdl, "SPLIT", cs%split, &
3708  "Use the split time stepping if true.", default=.true.)
3709  if (.not.cs%split) return
3710 
3711  ! ### USE SOMETHING OTHER THAN MAXVEL FOR THIS...
3712  call get_param(param_file, mdl, "BOUND_BT_CORRECTION", cs%bound_BT_corr, &
3713  "If true, the corrective pseudo mass-fluxes into the \n"//&
3714  "barotropic solver are limited to values that require \n"//&
3715  "less than 0.1*MAXVEL to be accommodated.",default=.false.)
3716  call get_param(param_file, mdl, "GRADUAL_BT_ICS", cs%gradual_BT_ICs, &
3717  "If true, adjust the initial conditions for the \n"//&
3718  "barotropic solver to the values from the layered \n"//&
3719  "solution over a whole timestep instead of instantly. \n"//&
3720  "This is a decent approximation to the inclusion of \n"//&
3721  "sum(u dh_dt) while also correcting for truncation errors.", &
3722  default=.false.)
3723  call get_param(param_file, mdl, "BT_USE_WIDE_HALOS", cs%use_wide_halos, &
3724  "If true, use wide halos and march in during the \n"//&
3725  "barotropic time stepping for efficiency.", default=.true., &
3726  layoutparam=.true.)
3727  call get_param(param_file, mdl, "BTHALO", bt_halo_sz, &
3728  "The minimum halo size for the barotropic solver.", default=0, &
3729  layoutparam=.true.)
3730 #ifdef STATIC_MEMORY_
3731  if ((bt_halo_sz > 0) .and. (bt_halo_sz /= bthalo_)) call mom_error(fatal, &
3732  "barotropic_init: Run-time values of BTHALO must agree with the \n"//&
3733  "macro BTHALO_ with STATIC_MEMORY_.")
3734  wd_halos(1) = whaloi_+nihalo_ ; wd_halos(2) = whaloj_+njhalo_
3735 #else
3736  wd_halos(1) = bt_halo_sz; wd_halos(2) = bt_halo_sz
3737 #endif
3738  call log_param(param_file, mdl, "!BT x-halo", wd_halos(1), &
3739  "The barotropic x-halo size that is actually used.", &
3740  layoutparam=.true.)
3741  call log_param(param_file, mdl, "!BT y-halo", wd_halos(2), &
3742  "The barotropic y-halo size that is actually used.", &
3743  layoutparam=.true.)
3744 
3745  call get_param(param_file, mdl, "USE_BT_CONT_TYPE", use_bt_cont_type, &
3746  "If true, use a structure with elements that describe \n"//&
3747  "effective face areas from the summed continuity solver \n"//&
3748  "as a function the barotropic flow in coupling between \n"//&
3749  "the barotropic and baroclinic flow. This is only used \n"//&
3750  "if SPLIT is true. \n", default=.true.)
3751  call get_param(param_file, mdl, "NONLINEAR_BT_CONTINUITY", &
3752  cs%Nonlinear_continuity, &
3753  "If true, use nonlinear transports in the barotropic \n"//&
3754  "continuity equation. This does not apply if \n"//&
3755  "USE_BT_CONT_TYPE is true.", default=.false.)
3756  cs%Nonlin_cont_update_period = 1
3757  if (cs%Nonlinear_continuity) &
3758  call get_param(param_file, mdl, "NONLIN_BT_CONT_UPDATE_PERIOD", &
3759  cs%Nonlin_cont_update_period, &
3760  "If NONLINEAR_BT_CONTINUITY is true, this is the number \n"//&
3761  "of barotropic time steps between updates to the face \n"//&
3762  "areas, or 0 to update only before the barotropic stepping.",&
3763  units="nondim", default=1)
3764  call get_param(param_file, mdl, "RESCALE_BT_FACE_AREAS", cs%rescale_D_bt, &
3765  "If true, the face areas used by the barotropic solver \n"//&
3766  "are rescaled to approximately reflect the open face \n"//&
3767  "areas of the interior layers. This probably requires \n"//&
3768  "FLUX_BT_COUPLING to work, and should not be used with \n"//&
3769  "USE_BT_CONT_TYPE.", default=.false.)
3770  call get_param(param_file, mdl, "BT_MASS_SOURCE_LIMIT", cs%eta_source_limit, &
3771  "The fraction of the initial depth of the ocean that can \n"//&
3772  "be added to or removed from the bartropic solution \n"//&
3773  "within a thermodynamic time step. By default this is 0 \n"//&
3774  "for no correction.", units="nondim", default=0.0)
3775  call get_param(param_file, mdl, "BT_PROJECT_VELOCITY", cs%BT_project_velocity,&
3776  "If true, step the barotropic velocity first and project \n"//&
3777  "out the velocity tendancy by 1+BEBT when calculating the \n"//&
3778  "transport. The default (false) is to use a predictor \n"//&
3779  "continuity step to find the pressure field, and then \n"//&
3780  "to do a corrector continuity step using a weighted \n"//&
3781  "average of the old and new velocities, with weights \n"//&
3782  "of (1-BEBT) and BEBT.", default=.false.)
3783 
3784  call get_param(param_file, mdl, "DYNAMIC_SURFACE_PRESSURE", cs%dynamic_psurf, &
3785  "If true, add a dynamic pressure due to a viscous ice \n"//&
3786  "shelf, for instance.", default=.false.)
3787  if (cs%dynamic_psurf) then
3788  call get_param(param_file, mdl, "ICE_LENGTH_DYN_PSURF", cs%ice_strength_length, &
3789  "The length scale at which the Rayleigh damping rate due \n"//&
3790  "to the ice strength should be the same as if a Laplacian \n"//&
3791  "were applied, if DYNAMIC_SURFACE_PRESSURE is true.", &
3792  units="m", default=1.0e4)
3793  call get_param(param_file, mdl, "DEPTH_MIN_DYN_PSURF", cs%Dmin_dyn_psurf, &
3794  "The minimum depth to use in limiting the size of the \n"//&
3795  "dynamic surface pressure for stability, if \n"//&
3796  "DYNAMIC_SURFACE_PRESSURE is true..", units="m", &
3797  default=1.0e-6)
3798  call get_param(param_file, mdl, "CONST_DYN_PSURF", cs%const_dyn_psurf, &
3799  "The constant that scales the dynamic surface pressure, \n"//&
3800  "if DYNAMIC_SURFACE_PRESSURE is true. Stable values \n"//&
3801  "are < ~1.0.", units="nondim", default=0.9)
3802  endif
3803 
3804  call get_param(param_file, mdl, "TIDES", cs%tides, &
3805  "If true, apply tidal momentum forcing.", default=.false.)
3806  call get_param(param_file, mdl, "SADOURNY", cs%Sadourny, &
3807  "If true, the Coriolis terms are discretized with the \n"//&
3808  "Sadourny (1975) energy conserving scheme, otherwise \n"//&
3809  "the Arakawa & Hsu scheme is used. If the internal \n"//&
3810  "deformation radius is not resolved, the Sadourny scheme \n"//&
3811  "should probably be used.", default=.true.)
3812 
3813  call get_param(param_file, mdl, "BT_THICK_SCHEME", hvel_str, &
3814  "A string describing the scheme that is used to set the \n"//&
3815  "open face areas used for barotropic transport and the \n"//&
3816  "relative weights of the accelerations. Valid values are:\n"//&
3817  "\t ARITHMETIC - arithmetic mean layer thicknesses \n"//&
3818  "\t HARMONIC - harmonic mean layer thicknesses \n"//&
3819  "\t HYBRID (the default) - use arithmetic means for \n"//&
3820  "\t layers above the shallowest bottom, the harmonic \n"//&
3821  "\t mean for layers below, and a weighted average for \n"//&
3822  "\t layers that straddle that depth \n"//&
3823  "\t FROM_BT_CONT - use the average thicknesses kept \n"//&
3824  "\t in the h_u and h_v fields of the BT_cont_type", &
3825  default=bt_cont_string)
3826  select case (hvel_str)
3827  case (hybrid_string) ; cs%hvel_scheme = hybrid
3828  case (harmonic_string) ; cs%hvel_scheme = harmonic
3829  case (arithmetic_string) ; cs%hvel_scheme = arithmetic
3830  case (bt_cont_string) ; cs%hvel_scheme = from_bt_cont
3831  case default
3832  call mom_mesg('barotropic_init: BT_THICK_SCHEME ="'//trim(hvel_str)//'"', 0)
3833  call mom_error(fatal, "barotropic_init: Unrecognized setting "// &
3834  "#define BT_THICK_SCHEME "//trim(hvel_str)//" found in input file.")
3835  end select
3836  if ((cs%hvel_scheme == from_bt_cont) .and. .not.use_bt_cont_type) &
3837  call mom_error(fatal, "barotropic_init: BT_THICK_SCHEME FROM_BT_CONT "//&
3838  "can only be used if USE_BT_CONT_TYPE is defined.")
3839 
3840  call get_param(param_file, mdl, "APPLY_BT_DRAG", apply_bt_drag, &
3841  "If defined, bottom drag is applied within the \n"//&
3842  "barotropic solver.", default=.true.)
3843  call get_param(param_file, mdl, "BT_STRONG_DRAG", cs%strong_drag, &
3844  "If true, use a stronger estimate of the retarding \n"//&
3845  "effects of strong bottom drag, by making it implicit \n"//&
3846  "with the barotropic time-step instead of implicit with \n"//&
3847  "the baroclinic time-step and dividing by the number of \n"//&
3848  "barotropic steps.", default=.true.)
3849 
3850  call get_param(param_file, mdl, "CLIP_BT_VELOCITY", cs%clip_velocity, &
3851  "If true, limit any velocity components that exceed \n"//&
3852  "MAXVEL. This should only be used as a desperate \n"//&
3853  "debugging measure.", default=.false.)
3854  call get_param(param_file, mdl, "MAXVEL", cs%maxvel, &
3855  "The maximum velocity allowed before the velocity \n"//&
3856  "components are truncated.", units="m s-1", default=3.0e8, &
3857  do_not_log=.not.cs%clip_velocity)
3858  call get_param(param_file, mdl, "MAXCFL_BT_CONT", cs%maxCFL_BT_cont, &
3859  "The maximum permitted CFL number associated with the \n"//&
3860  "barotropic accelerations from the summed velocities \n"//&
3861  "times the time-derivatives of thicknesses.", units="nondim", &
3862  default=0.1)
3863 
3864  call get_param(param_file, mdl, "DT_BT_FILTER", cs%dt_bt_filter, &
3865  "A time-scale over which the barotropic mode solutions \n"//&
3866  "are filtered, in seconds if positive, or as a fraction \n"//&
3867  "of DT if negative. When used this can never be taken to \n"//&
3868  "be longer than 2*dt. Set this to 0 to apply no filtering.", &
3869  units="sec or nondim", default=-0.25)
3870  call get_param(param_file, mdl, "G_BT_EXTRA", cs%G_extra, &
3871  "A nondimensional factor by which gtot is enhanced.", &
3872  units="nondim", default=0.0)
3873  call get_param(param_file, mdl, "SSH_EXTRA", ssh_extra, &
3874  "An estimate of how much higher SSH might get, for use \n"//&
3875  "in calculating the safe external wave speed. The \n"//&
3876  "default is the minimum of 10 m or 5% of MAXIMUM_DEPTH.", &
3877  units="m", default=min(10.0,0.05*g%max_depth))
3878 
3879  call get_param(param_file, mdl, "DEBUG", cs%debug, &
3880  "If true, write out verbose debugging data.", default=.false.)
3881  call get_param(param_file, mdl, "DEBUG_BT", cs%debug_bt, &
3882  "If true, write out verbose debugging data within the \n"//&
3883  "barotropic time-stepping loop. The data volume can be \n"//&
3884  "quite large if this is true.", default=cs%debug)
3885 
3886  cs%linearized_BT_PV = .true.
3887  call get_param(param_file, mdl, "BEBT", cs%bebt, &
3888  "BEBT determines whether the barotropic time stepping \n"//&
3889  "uses the forward-backward time-stepping scheme or a \n"//&
3890  "backward Euler scheme. BEBT is valid in the range from \n"//&
3891  "0 (for a forward-backward treatment of nonrotating \n"//&
3892  "gravity waves) to 1 (for a backward Euler treatment). \n"//&
3893  "In practice, BEBT must be greater than about 0.05.", &
3894  units="nondim", default=0.1)
3895  call get_param(param_file, mdl, "DTBT", cs%dtbt, &
3896  "The barotropic time step, in s. DTBT is only used with \n"//&
3897  "the split explicit time stepping. To set the time step \n"//&
3898  "automatically based the maximum stable value use 0, or \n"//&
3899  "a negative value gives the fraction of the stable value. \n"//&
3900  "Setting DTBT to 0 is the same as setting it to -0.98. \n"//&
3901  "The value of DTBT that will actually be used is an \n"//&
3902  "integer fraction of DT, rounding down.", units="s or nondim",&
3903  default = -0.98)
3904 
3905 
3906  if (apply_bt_drag) then ; cs%drag_amp = 1.0 ; else ; cs%drag_amp = 0.0 ; endif
3907 
3908  ! Initialize a version of the MOM domain that is specific to the barotropic solver.
3909  call clone_mom_domain(g%Domain, cs%BT_Domain, min_halo=wd_halos, symmetric=.true.)
3910 #ifdef STATIC_MEMORY_
3911  if (wd_halos(1) /= whaloi_+nihalo_) call mom_error(fatal, "barotropic_init: "//&
3912  "Barotropic x-halo sizes are incorrectly resized with STATIC_MEMORY_.")
3913  if (wd_halos(2) /= whaloj_+njhalo_) call mom_error(fatal, "barotropic_init: "//&
3914  "Barotropic y-halo sizes are incorrectly resized with STATIC_MEMORY_.")
3915 #else
3916  if (bt_halo_sz > 0) then
3917  if (wd_halos(1) > bt_halo_sz) &
3918  call mom_mesg("barotropic_init: barotropic x-halo size increased.", 3)
3919  if (wd_halos(2) > bt_halo_sz) &
3920  call mom_mesg("barotropic_init: barotropic y-halo size increased.", 3)
3921  endif
3922 #endif
3923 
3924  cs%isdw = g%isc-wd_halos(1) ; cs%iedw = g%iec+wd_halos(1)
3925  cs%jsdw = g%jsc-wd_halos(2) ; cs%jedw = g%jec+wd_halos(2)
3926  isdw = cs%isdw ; iedw = cs%iedw ; jsdw = cs%jsdw ; jedw = cs%jedw
3927 
3928  alloc_(cs%frhatu(isdb:iedb,jsd:jed,nz)) ; alloc_(cs%frhatv(isd:ied,jsdb:jedb,nz))
3929  alloc_(cs%eta_source(isd:ied,jsd:jed)) ; alloc_(cs%eta_cor(isd:ied,jsd:jed))
3930  if (cs%bound_BT_corr) then
3931  alloc_(cs%eta_cor_bound(isd:ied,jsd:jed)) ; cs%eta_cor_bound(:,:) = 0.0
3932  endif
3933  alloc_(cs%IDatu(isdb:iedb,jsd:jed)) ; alloc_(cs%IDatv(isd:ied,jsdb:jedb))
3934 
3935  alloc_(cs%Datu_res(isdw-1:iedw,jsdw:jedw))
3936  alloc_(cs%Datv_res(isdw:iedw,jsdw-1:jedw))
3937  alloc_(cs%ua_polarity(isdw:iedw,jsdw:jedw))
3938  alloc_(cs%va_polarity(isdw:iedw,jsdw:jedw))
3939 
3940  cs%frhatu(:,:,:) = 0.0 ; cs%frhatv(:,:,:) = 0.0
3941  cs%eta_source(:,:) = 0.0 ; cs%eta_cor(:,:) = 0.0
3942  cs%IDatu(:,:) = 0.0 ; cs%IDatv(:,:) = 0.0
3943  cs%Datu_res(:,:) = 1.0 ; cs%Datv_res(:,:) = 1.0
3944 
3945  cs%ua_polarity(:,:) = 1.0 ; cs%va_polarity(:,:) = 1.0
3946  call pass_vector(cs%ua_polarity, cs%va_polarity, cs%BT_domain, to_all, agrid)
3947 
3948  if (use_bt_cont_type) &
3949  call alloc_bt_cont_type(bt_cont, g, (cs%hvel_scheme == from_bt_cont))
3950 
3951  if (cs%debug) then ! Make a local copy of loop ranges for chksum calls
3952  allocate(cs%debug_BT_HI)
3953  cs%debug_BT_HI%isc=g%isc
3954  cs%debug_BT_HI%iec=g%iec
3955  cs%debug_BT_HI%jsc=g%jsc
3956  cs%debug_BT_HI%jec=g%jec
3957  cs%debug_BT_HI%IscB=g%isc-1
3958  cs%debug_BT_HI%IecB=g%iec
3959  cs%debug_BT_HI%JscB=g%jsc-1
3960  cs%debug_BT_HI%JecB=g%jec
3961  cs%debug_BT_HI%isd=cs%isdw
3962  cs%debug_BT_HI%ied=cs%iedw
3963  cs%debug_BT_HI%jsd=cs%jsdw
3964  cs%debug_BT_HI%jed=cs%jedw
3965  cs%debug_BT_HI%IsdB=cs%isdw-1
3966  cs%debug_BT_HI%IedB=cs%iedw
3967  cs%debug_BT_HI%JsdB=cs%jsdw-1
3968  cs%debug_BT_HI%JedB=cs%jedw
3969 
3970  endif
3971 
3972  ! IareaT, IdxCu, and IdyCv need to be allocated with wide halos.
3973  alloc_(cs%IareaT(cs%isdw:cs%iedw,cs%jsdw:cs%jedw)) ; cs%IareaT(:,:) = 0.0
3974  alloc_(cs%bathyT(cs%isdw:cs%iedw,cs%jsdw:cs%jedw)) ; cs%bathyT(:,:) = gv%Angstrom_z !### Should this be 0 instead?
3975  alloc_(cs%IdxCu(cs%isdw-1:cs%iedw,cs%jsdw:cs%jedw)) ; cs%IdxCu(:,:) = 0.0
3976  alloc_(cs%IdyCv(cs%isdw:cs%iedw,cs%jsdw-1:cs%jedw)) ; cs%IdyCv(:,:) = 0.0
3977  alloc_(cs%dy_Cu(cs%isdw-1:cs%iedw,cs%jsdw:cs%jedw)) ; cs%dy_Cu(:,:) = 0.0
3978  alloc_(cs%dx_Cv(cs%isdw:cs%iedw,cs%jsdw-1:cs%jedw)) ; cs%dx_Cv(:,:) = 0.0
3979  do j=g%jsd,g%jed ; do i=g%isd,g%ied
3980  cs%IareaT(i,j) = g%IareaT(i,j)
3981  cs%bathyT(i,j) = g%bathyT(i,j)
3982  enddo ; enddo
3983  ! Note: G%IdxCu & G%IdyCv may be smaller than CS%IdxCu & CS%IdyCv, even without
3984  ! wide halos.
3985  do j=g%jsd,g%jed ; do i=g%IsdB,g%IedB
3986  cs%IdxCu(i,j) = g%IdxCu(i,j) ; cs%dy_Cu(i,j) = g%dy_Cu(i,j)
3987  enddo ; enddo
3988  do j=g%JsdB,g%JedB ; do i=g%isd,g%ied
3989  cs%IdyCv(i,j) = g%IdyCv(i,j) ; cs%dx_Cv(i,j) = g%dx_Cv(i,j)
3990  enddo ; enddo
3991  call pass_var(cs%IareaT, cs%BT_domain, to_all)
3992  call pass_var(cs%bathyT, cs%BT_domain, to_all)
3993  call pass_vector(cs%IdxCu, cs%IdyCv, cs%BT_domain, to_all+scalar_pair)
3994  call pass_vector(cs%dy_Cu, cs%dx_Cv, cs%BT_domain, to_all+scalar_pair)
3995 
3996  if (cs%linearized_BT_PV) then
3997  alloc_(cs%q_D(cs%isdw-1:cs%iedw,cs%jsdw-1:cs%jedw))
3998  alloc_(cs%D_u_Cor(cs%isdw-1:cs%iedw,cs%jsdw:cs%jedw))
3999  alloc_(cs%D_v_Cor(cs%isdw:cs%iedw,cs%jsdw-1:cs%jedw))
4000  cs%q_D(:,:) = 0.0 ; cs%D_u_Cor(:,:) = 0.0 ; cs%D_v_Cor(:,:) = 0.0
4001  do j=js,je ; do i=is-1,ie
4002  cs%D_u_Cor(i,j) = 0.5 * (g%bathyT(i+1,j) + g%bathyT(i,j))
4003  enddo ; enddo
4004  do j=js-1,je ; do i=is,ie
4005  cs%D_v_Cor(i,j) = 0.5 * (g%bathyT(i,j+1) + g%bathyT(i,j))
4006  enddo ; enddo
4007  do j=js-1,je ; do i=is-1,ie
4008  cs%q_D(i,j) = 0.25 * g%CoriolisBu(i,j) * &
4009  ((g%areaT(i,j) + g%areaT(i+1,j+1)) + (g%areaT(i+1,j) + g%areaT(i,j+1))) / &
4010  ((g%areaT(i,j) * g%bathyT(i,j) + g%areaT(i+1,j+1) * g%bathyT(i+1,j+1)) + &
4011  (g%areaT(i+1,j) * g%bathyT(i+1,j) + g%areaT(i,j+1) * g%bathyT(i,j+1)))
4012  enddo ; enddo
4013  ! With very wide halos, q and D need to be calculated on the available data
4014  ! domain and then updated onto the full computational domain.
4015  call pass_var(cs%q_D, cs%BT_Domain, to_all, position=corner)
4016  call pass_vector(cs%D_u_Cor, cs%D_v_Cor, cs%BT_Domain, to_all+scalar_pair)
4017  endif
4018 
4019  ! Estimate the maximum stable barotropic time step.
4020  dtbt_input = cs%dtbt
4021  cs%dtbt_fraction = 0.98 ; if (cs%dtbt < 0.0) cs%dtbt_fraction = -cs%dtbt
4022  gtot_estimate = 0.0
4023  do k=1,g%ke ; gtot_estimate = gtot_estimate + gv%g_prime(k) ; enddo
4024  call legacy_set_dtbt(g, gv, cs, gtot_est = gtot_estimate, ssh_add = ssh_extra)
4025  if (dtbt_input > 0.0) cs%dtbt = dtbt_input
4026 
4027  call log_param(param_file, mdl, "!DTBT as used", cs%dtbt)
4028  call log_param(param_file, mdl, "!estimated maximum DTBT", cs%dtbt_max)
4029 
4030  ! ubtav, vbtav, ubt_IC, vbt_IC, uhbt_IC, and vhbt_IC are allocated and
4031  ! initialized in register_barotropic_restarts.
4032 
4033  if (gv%Boussinesq) then
4034  thickness_units = "meter" ; flux_units = "meter3 second-1"
4035  else
4036  thickness_units = "kilogram meter-2" ; flux_units = "kilogram second-1"
4037  endif
4038 
4039  cs%id_PFu_bt = register_diag_field('ocean_model', 'PFuBT', diag%axesCu1, time, &
4040  'Zonal Anomalous Barotropic Pressure Force Force Acceleration', 'meter second-2')
4041  cs%id_PFv_bt = register_diag_field('ocean_model', 'PFvBT', diag%axesCv1, time, &
4042  'Meridional Anomalous Barotropic Pressure Force Acceleration', 'meter second-2')
4043  cs%id_Coru_bt = register_diag_field('ocean_model', 'CoruBT', diag%axesCu1, time, &
4044  'Zonal Barotropic Coriolis Acceleration', 'meter second-2')
4045  cs%id_Corv_bt = register_diag_field('ocean_model', 'CorvBT', diag%axesCv1, time, &
4046  'Meridional Barotropic Coriolis Acceleration', 'meter second-2')
4047  cs%id_uaccel = register_diag_field('ocean_model', 'u_accel_bt', diag%axesCu1, time, &
4048  'Barotropic zonal acceleration', 'meter second-2')
4049  cs%id_vaccel = register_diag_field('ocean_model', 'v_accel_bt', diag%axesCv1, time, &
4050  'Barotropic meridional acceleration', 'meter second-2')
4051  cs%id_ubtforce = register_diag_field('ocean_model', 'ubtforce', diag%axesCu1, time, &
4052  'Barotropic zonal acceleration from baroclinic terms', 'meter second-2')
4053  cs%id_vbtforce = register_diag_field('ocean_model', 'vbtforce', diag%axesCv1, time, &
4054  'Barotropic meridional acceleration from baroclinic terms', 'meter second-2')
4055 
4056  cs%id_eta_bt = register_diag_field('ocean_model', 'eta_bt', diag%axesT1, time, &
4057  'Barotropic end SSH', thickness_units)
4058  cs%id_ubt = register_diag_field('ocean_model', 'ubt', diag%axesCu1, time, &
4059  'Barotropic end zonal velocity', 'meter second-1')
4060  cs%id_vbt = register_diag_field('ocean_model', 'vbt', diag%axesCv1, time, &
4061  'Barotropic end meridional velocity', 'meter second-1')
4062  cs%id_eta_st = register_diag_field('ocean_model', 'eta_st', diag%axesT1, time, &
4063  'Barotropic start SSH', thickness_units)
4064  cs%id_ubt_st = register_diag_field('ocean_model', 'ubt_st', diag%axesCu1, time, &
4065  'Barotropic start zonal velocity', 'meter second-1')
4066  cs%id_vbt_st = register_diag_field('ocean_model', 'vbt_st', diag%axesCv1, time, &
4067  'Barotropic start meridional velocity', 'meter second-1')
4068  cs%id_ubtav = register_diag_field('ocean_model', 'ubtav', diag%axesCu1, time, &
4069  'Barotropic time-average zonal velocity', 'meter second-1')
4070  cs%id_vbtav = register_diag_field('ocean_model', 'vbtav', diag%axesCv1, time, &
4071  'Barotropic time-average meridional velocity', 'meter second-1')
4072  cs%id_eta_cor = register_diag_field('ocean_model', 'eta_cor', diag%axesT1, time, &
4073  'Corrective mass flux', 'meter second-1')
4074  cs%id_visc_rem_u = register_diag_field('ocean_model', 'visc_rem_u', diag%axesCuL, time, &
4075  'Viscous remnant at u', 'Nondim')
4076  cs%id_visc_rem_v = register_diag_field('ocean_model', 'visc_rem_v', diag%axesCvL, time, &
4077  'Viscous remnant at v', 'Nondim')
4078  cs%id_gtotn = register_diag_field('ocean_model', 'gtot_n', diag%axesT1, time, &
4079  'gtot to North', 'm s-2')
4080  cs%id_gtots = register_diag_field('ocean_model', 'gtot_s', diag%axesT1, time, &
4081  'gtot to South', 'm s-2')
4082  cs%id_gtote = register_diag_field('ocean_model', 'gtot_e', diag%axesT1, time, &
4083  'gtot to East', 'm s-2')
4084  cs%id_gtotw = register_diag_field('ocean_model', 'gtot_w', diag%axesT1, time, &
4085  'gtot to West', 'm s-2')
4086  cs%id_eta_hifreq = register_diag_field('ocean_model', 'eta_hifreq', diag%axesT1, time, &
4087  'High Frequency Barotropic SSH', thickness_units)
4088  cs%id_ubt_hifreq = register_diag_field('ocean_model', 'ubt_hifreq', diag%axesCu1, time, &
4089  'High Frequency Barotropic zonal velocity', 'meter second-1')
4090  cs%id_vbt_hifreq = register_diag_field('ocean_model', 'vbt_hifreq', diag%axesCv1, time, &
4091  'High Frequency Barotropic meridional velocity', 'meter second-1')
4092  cs%id_eta_pred_hifreq = register_diag_field('ocean_model', 'eta_pred_hifreq', diag%axesT1, time, &
4093  'High Frequency Predictor Barotropic SSH', thickness_units)
4094  cs%id_uhbt_hifreq = register_diag_field('ocean_model', 'uhbt_hifreq', diag%axesCu1, time, &
4095  'High Frequency Barotropic zonal transport', 'meter3 second-1')
4096  cs%id_vhbt_hifreq = register_diag_field('ocean_model', 'vhbt_hifreq', diag%axesCv1, time, &
4097  'High Frequency Barotropic meridional transport', 'meter3 second-1')
4098  if (cs%rescale_D_bt) then
4099  cs%id_Datu_res = register_diag_field('ocean_model', 'Datu_res', diag%axesCu1, time, &
4100  'Rescaling for zonal face area in barotropic continuity', 'Nondimensional')
4101  cs%id_Datv_res = register_diag_field('ocean_model', 'Datv_res', diag%axesCv1, time, &
4102  'Rescaling for meridional face area in barotropic continuity', 'Nondimensional')
4103  endif
4104  cs%id_frhatu = register_diag_field('ocean_model', 'frhatu', diag%axesCuL, time, &
4105  'Fractional thickness of layers in u-columns', 'Nondim')
4106  cs%id_frhatv = register_diag_field('ocean_model', 'frhatv', diag%axesCvL, time, &
4107  'Fractional thickness of layers in v-columns', 'Nondim')
4108  cs%id_frhatu1 = register_diag_field('ocean_model', 'frhatu1', diag%axesCuL, time, &
4109  'Predictor Fractional thickness of layers in u-columns', 'Nondim')
4110  cs%id_frhatv1 = register_diag_field('ocean_model', 'frhatv1', diag%axesCvL, time, &
4111  'Predictor Fractional thickness of layers in v-columns', 'Nondim')
4112  cs%id_uhbt = register_diag_field('ocean_model', 'uhbt', diag%axesCu1, time, &
4113  'Barotropic zonal transport averaged over a baroclinic step', 'meter3 second-1')
4114  cs%id_vhbt = register_diag_field('ocean_model', 'vhbt', diag%axesCv1, time, &
4115  'Barotropic meridional transport averaged over a baroclinic step', 'meter3 second-1')
4116 
4117  if (cs%id_frhatu1 > 0) call safe_alloc_ptr(cs%frhatu1, isdb,iedb,jsd,jed,nz)
4118  if (cs%id_frhatv1 > 0) call safe_alloc_ptr(cs%frhatv1, isd,ied,jsdb,jedb,nz)
4119 
4120  if (.NOT.query_initialized(cs%ubtav,"ubtav",restart_cs) .or. &
4121  .NOT.query_initialized(cs%vbtav,"vbtav",restart_cs)) then
4122  call legacy_btcalc(h, g, gv, cs, may_use_default=.true.)
4123  do j=js-1,je+1 ; do i=is-1,ie+1
4124  cs%ubtav(i,j) = 0.0 ; cs%vbtav(i,j) = 0.0
4125  enddo ; enddo
4126  do k=1,nz ; do j=js-1,je+1 ; do i=is-1,ie+1
4127  cs%ubtav(i,j) = cs%ubtav(i,j) + cs%frhatu(i,j,k) * u(i,j,k)
4128  cs%vbtav(i,j) = cs%vbtav(i,j) + cs%frhatv(i,j,k) * v(i,j,k)
4129  enddo ; enddo ; enddo
4130  endif
4131 
4132  if (.NOT.query_initialized(cs%ubt_IC,"ubt_IC",restart_cs) .or. &
4133  .NOT.query_initialized(cs%vbt_IC,"vbt_IC",restart_cs)) then
4134  do j=js,je ; do i=is-1,ie ; cs%ubt_IC(i,j) = cs%ubtav(i,j) ; enddo ; enddo
4135  do j=js-1,je ; do i=is,ie ; cs%vbt_IC(i,j) = cs%vbtav(i,j) ; enddo ; enddo
4136  endif
4137 
4138 ! Calculate other constants which are used for btstep.
4139 
4140  ! The following is only valid with the Boussinesq approximation.
4141 ! if (GV%Boussinesq) then
4142  do j=js,je ; do i=is-1,ie
4143  cs%IDatu(i,j) = g%mask2dCu(i,j) * 2.0 / (g%bathyT(i+1,j) + g%bathyT(i,j))
4144  enddo ; enddo
4145  do j=js-1,je ; do i=is,ie
4146  cs%IDatv(i,j) = g%mask2dCv(i,j) * 2.0 / (g%bathyT(i,j+1) + g%bathyT(i,j))
4147  enddo ; enddo
4148 ! else
4149 ! do j=js,je ; do I=is-1,ie
4150 ! CS%IDatu(I,j) = G%mask2dCu(I,j) * 2.0 / (GV%Rho0*(G%bathyT(i+1,j) + G%bathyT(i,j)))
4151 ! enddo ; enddo
4152 ! do J=js-1,je ; do i=is,ie
4153 ! CS%IDatv(i,J) = G%mask2dCv(i,J) * 2.0 / (GV%Rho0*(G%bathyT(i,j+1) + G%bathyT(i,j)))
4154 ! enddo ; enddo
4155 ! endif
4156 
4157  call find_face_areas(datu, datv, g, gv, cs, ms, halo=1)
4158  if (cs%bound_BT_corr) then
4159  do j=js,je ; do i=is,ie
4160  cs%eta_cor_bound(i,j) = gv%m_to_H * g%IareaT(i,j) * 0.1 * cs%maxvel * &
4161  ((datu(i-1,j) + datu(i,j)) + (datv(i,j) + datv(i,j-1)))
4162  enddo ; enddo
4163  endif
4164 
4165  if (.NOT.query_initialized(cs%uhbt_IC,"uhbt_IC",restart_cs) .or. &
4166  .NOT.query_initialized(cs%vhbt_IC,"vhbt_IC",restart_cs)) then
4167  do j=js,je ; do i=is-1,ie ; cs%uhbt_IC(i,j) = cs%ubtav(i,j) * datu(i,j) ; enddo ; enddo
4168  do j=js-1,je ; do i=is,ie ; cs%vhbt_IC(i,j) = cs%vbtav(i,j) * datv(i,j) ; enddo ; enddo
4169  endif
4170 
4171  call pass_vector(cs%ubt_IC, cs%vbt_IC, g%Domain, complete=.false.)
4172  call pass_vector(cs%uhbt_IC, cs%vhbt_IC, g%Domain, complete=.false.)
4173  call pass_vector(cs%ubtav, cs%vbtav, g%Domain)
4174 
4175 
4176 ! id_clock_pass = cpu_clock_id('(Ocean BT halo updates)', grain=CLOCK_ROUTINE)
4177  id_clock_calc_pre = cpu_clock_id('(Ocean BT pre-calcs only)', grain=clock_routine)
4178  id_clock_pass_pre = cpu_clock_id('(Ocean BT pre-step halo updates)', grain=clock_routine)
4179  id_clock_calc = cpu_clock_id('(Ocean BT stepping calcs only)', grain=clock_routine)
4180  id_clock_pass_step = cpu_clock_id('(Ocean BT stepping halo updates)', grain=clock_routine)
4181  id_clock_calc_post = cpu_clock_id('(Ocean BT post-calcs only)', grain=clock_routine)
4182  id_clock_pass_post = cpu_clock_id('(Ocean BT post-step halo updates)', grain=clock_routine)
4183  if (dtbt_input <= 0.0) &
4184  id_clock_sync = cpu_clock_id('(Ocean BT global synch)', grain=clock_routine)
4185 
4186 end subroutine legacy_barotropic_init
4187 
4188 subroutine legacy_barotropic_end(CS)
4189  type(legacy_barotropic_cs), pointer :: CS
4190  dealloc_(cs%frhatu) ; dealloc_(cs%frhatv)
4191  dealloc_(cs%IDatu) ; dealloc_(cs%IDatv)
4192  dealloc_(cs%Datu_res) ; dealloc_(cs%Datv_res)
4193  dealloc_(cs%ubtav) ; dealloc_(cs%vbtav)
4194  dealloc_(cs%eta_cor) ; dealloc_(cs%eta_source)
4195  dealloc_(cs%ua_polarity) ; dealloc_(cs%va_polarity)
4196  if (cs%bound_BT_corr) then
4197  dealloc_(cs%eta_cor_bound)
4198  endif
4199 
4200  deallocate(cs)
4201 end subroutine legacy_barotropic_end
4202 
4203 !> This subroutine is used to register any fields from MOM_barotropic.F90
4204 !! that should be written to or read from the restart file.
4205 subroutine register_legacy_barotropic_restarts(HI, GV, param_file, CS, restart_CS)
4206  type(hor_index_type), intent(in) :: HI !< A horizontal index type structure.
4207  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
4208  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters.
4209  type(legacy_barotropic_cs), pointer :: CS !< A pointer that is set to point to the control
4210  !! structure for this module.
4211  type(mom_restart_cs), pointer :: restart_CS !< A pointer to the restart control structure.
4212 ! This subroutine is used to register any fields from MOM_barotropic.F90
4213 ! that should be written to or read from the restart file.
4214 ! Arguments: HI - A horizontal index type structure.
4215 ! (in) GV - The ocean's vertical grid structure.
4216 ! (in/out) CS - A pointer that is set to point to the control structure
4217 ! for this module
4218 ! (in) restart_CS - A pointer to the restart control structure.
4219  type(vardesc) :: vd(3)
4220  real :: slow_rate
4221  integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB
4222  isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed
4223  isdb = hi%IsdB ; iedb = hi%IedB ; jsdb = hi%JsdB ; jedb = hi%JedB
4224 
4225  if (associated(cs)) then
4226  call mom_error(warning, "register_barotropic_restarts called with an associated "// &
4227  "control structure.")
4228  return
4229  endif
4230  allocate(cs)
4231 
4232  alloc_(cs%ubtav(isdb:iedb,jsd:jed)) ; cs%ubtav(:,:) = 0.0
4233  alloc_(cs%vbtav(isd:ied,jsdb:jedb)) ; cs%vbtav(:,:) = 0.0
4234  alloc_(cs%ubt_IC(isdb:iedb,jsd:jed)) ; cs%ubt_IC(:,:) = 0.0
4235  alloc_(cs%vbt_IC(isd:ied,jsdb:jedb)) ; cs%vbt_IC(:,:) = 0.0
4236  alloc_(cs%uhbt_IC(isdb:iedb,jsd:jed)) ; cs%uhbt_IC(:,:) = 0.0
4237  alloc_(cs%vhbt_IC(isd:ied,jsdb:jedb)) ; cs%vhbt_IC(:,:) = 0.0
4238 
4239  vd(2) = var_desc("ubtav","meter second-1","Time mean barotropic zonal velocity", &
4240  hor_grid='u', z_grid='1')
4241  vd(3) = var_desc("vbtav","meter second-1","Time mean barotropic meridional velocity",&
4242  hor_grid='v', z_grid='1')
4243  call register_restart_field(cs%ubtav, vd(2), .false., restart_cs)
4244  call register_restart_field(cs%vbtav, vd(3), .false., restart_cs)
4245 
4246  vd(2) = var_desc("ubt_IC", "meter second-1", &
4247  longname="Next initial condition for the barotropic zonal velocity", &
4248  hor_grid='u', z_grid='1')
4249  vd(3) = var_desc("vbt_IC", "meter second-1", &
4250  longname="Next initial condition for the barotropic meridional velocity",&
4251  hor_grid='v', z_grid='1')
4252  call register_restart_field(cs%ubt_IC, vd(2), .false., restart_cs)
4253  call register_restart_field(cs%vbt_IC, vd(3), .false., restart_cs)
4254 
4255  if (gv%Boussinesq) then
4256  vd(2) = var_desc("uhbt_IC", "meter3 second-1", &
4257  longname="Next initial condition for the barotropic zonal transport", &
4258  hor_grid='u', z_grid='1')
4259  vd(3) = var_desc("vhbt_IC", "meter3 second-1", &
4260  longname="Next initial condition for the barotropic meridional transport",&
4261  hor_grid='v', z_grid='1')
4262  else
4263  vd(2) = var_desc("uhbt_IC", "kg second-1", &
4264  longname="Next initial condition for the barotropic zonal transport", &
4265  hor_grid='u', z_grid='1')
4266  vd(3) = var_desc("vhbt_IC", "kg second-1", &
4267  longname="Next initial condition for the barotropic meridional transport",&
4268  hor_grid='v', z_grid='1')
4269  endif
4270  call register_restart_field(cs%uhbt_IC, vd(2), .false., restart_cs)
4271  call register_restart_field(cs%vhbt_IC, vd(3), .false., restart_cs)
4272 
4274 
4275 end module mom_legacy_barotropic
real function find_uhbt(u, BTC)
integer, parameter, public obc_direction_s
Indicates the boundary is an effective southern boundary.
real function find_vhbt(v, BTC)
subroutine, public tidal_forcing_sensitivity(G, CS, deta_tidal_deta)
This subroutine calculates returns the partial derivative of the local geopotential height with the i...
integer, parameter, public obc_direction_w
Indicates the boundary is an effective western boundary.
type(vardesc) function, public var_desc(name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
Returns a vardesc type whose elements have been filled with the provided fields. The argument name is...
Definition: MOM_io.F90:585
subroutine, public legacy_bt_mass_source(h, eta, fluxes, set_cor, dt_therm, dt_since_therm, G, GV, CS)
integer, parameter, public obc_direction_n
Indicates the boundary is an effective northern boundary.
subroutine, public alloc_bt_cont_type(BT_cont, G, alloc_faces)
alloc_BT_cont_type allocates the arrays contained within a BT_cont_type and initializes them to 0...
character *(20), parameter bt_cont_string
This module implements boundary forcing for MOM6.
subroutine, public enable_averaging(time_int_in, time_end_in, diag_cs)
integer, parameter, public to_all
character *(20), parameter arithmetic_string
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
subroutine destroy_bt_obc(BT_OBC)
character *(20), parameter hybrid_string
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
subroutine, public register_legacy_barotropic_restarts(HI, GV, param_file, CS, restart_CS)
This subroutine is used to register any fields from MOM_barotropic.F90 that should be written to or r...
subroutine find_face_areas(Datu, Datv, G, GV, CS, MS, rescale_faces, eta, halo, add_max)
Provides the ocean grid type.
Definition: MOM_grid.F90:2
Open boundary segment data structure.
subroutine apply_eta_obcs(OBC, eta, ubt, vbt, BT_OBC, G, MS, halo, dtbt)
This subroutine applies the open boundary conditions on the free surface height, as coded by Mehmet I...
This module contains I/O framework code.
Definition: MOM_io.F90:2
Defines the horizontal index type (hor_index_type) used for providing index ranges.
subroutine set_local_bt_cont_types(BT_cont, BTCL_u, BTCL_v, G, MS, BT_Domain, halo)
Container for horizontal index ranges for data, computational and global domains. ...
subroutine, public legacy_barotropic_end(CS)
integer, parameter, public obc_simple
subroutine set_up_bt_obc(OBC, eta, BT_OBC, G, GV, MS, halo, use_BT_cont, Datu, Datv, BTCL_u, BTCL_v)
This subroutine sets up the private structure used to apply the open boundary conditions, as developed by Mehmet Ilicak.
logical function, public query_averaging_enabled(diag_cs, time_int, time_end)
The BT_cont_type structure contains information about the summed layer transports and how they will v...
integer, parameter, public obc_flather
character *(20), parameter harmonic_string
logical function, public is_root_pe()
integer, parameter hybrid_bt_cont
subroutine, public legacy_barotropic_init(u, v, h, eta, Time, G, GV, param_file, diag, CS, restart_CS, BT_cont, tides_CSp)
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
subroutine, public mom_mesg(message, verb, all_print)
integer, parameter, public obc_direction_e
Indicates the boundary is an effective eastern boundary.
Type for describing a variable, typically a tracer.
Definition: MOM_io.F90:51
subroutine apply_velocity_obcs(OBC, ubt, vbt, uhbt, vhbt, ubt_trans, vbt_trans, eta, ubt_old, vbt_old, BT_OBC, G, MS, halo, dtbt, bebt, use_BT_cont, Datu, Datv, BTCL_u, BTCL_v, uhbt0, vhbt0)
This subroutine applies the open boundary conditions on barotropic velocities and mass transports...
subroutine, public legacy_set_dtbt(G, GV, CS, eta, pbce, BT_cont, gtot_est, SSH_add)
The MOM_domain_type contains information about the domain decompositoin.
real function uhbt_to_ubt(uhbt, BTC, guess)
subroutine, public legacy_btstep(use_fluxes, U_in, V_in, eta_in, dt, bc_accel_u, bc_accel_v, fluxes, pbce, eta_PF_in, U_Cor, V_Cor, accel_layer_u, accel_layer_v, eta_out, uhbtav, vhbtav, G, GV, CS, visc_rem_u, visc_rem_v, etaav, uhbt_out, vhbt_out, OBC, BT_cont, eta_PF_start, taux_bot, tauy_bot, uh0, vh0, u_uh0, v_vh0)
subroutine bt_cont_to_face_areas(BT_cont, Datu, Datv, G, MS, halo, maximize)
integer, parameter, public obc_none
real function vhbt_to_vbt(vhbt, BTC, guess)
Controls where open boundary conditions are applied.
integer function, public register_diag_field(module_name, field_name, axes, init_time, long_name, units, missing_value, range, mask_variant, standard_name, verbose, do_not_log, err_msg, interp_method, tile_count, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name, cell_methods, x_cell_method, y_cell_method, v_cell_method, conversion, v_extensive)
Returns the "diag_mediator" handle for a group (native, CMOR, z-coord, ...) of diagnostics derived fr...
subroutine, public mom_error(level, message, all_print)
subroutine, public legacy_btcalc(h, G, GV, CS, h_u, h_v, may_use_default)
This subroutine calculates the barotropic velocities from the full velocity and thickness fields...
integer, parameter from_bt_cont