← back to index

src/parameterizations/vertical/MOM_bulk_mixed_layer.F90

portedportable, not yet portedexecuted, not portableexecutable, not hit by this run

1! This file is part of MOM6, the Modular Ocean Model version 6.
2! See the LICENSE file for licensing information.
3! SPDX-License-Identifier: Apache-2.0
4
5!> Build mixed layer parameterization
6module MOM_bulk_mixed_layer
7
8use MOM_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, CLOCK_ROUTINE
9use MOM_diag_mediator, only : post_data, register_diag_field, safe_alloc_alloc
10use MOM_diag_mediator, only : time_type, diag_ctrl, diag_update_remap_grids
11use MOM_domains, only : create_group_pass, do_group_pass, group_pass_type
12use MOM_EOS, only : calculate_density, calculate_density_derivs, EOS_domain
13use MOM_EOS, only : average_specific_vol, calculate_density_derivs
14use MOM_EOS, only : calculate_spec_vol, calculate_specific_vol_derivs
15use MOM_error_handler, only : MOM_error, FATAL, WARNING
16use MOM_file_parser, only : get_param, log_param, log_version, param_file_type
17use MOM_forcing_type, only : extractFluxes1d, forcing, find_ustar
18use MOM_grid, only : ocean_grid_type
19use MOM_opacity, only : absorbRemainingSW, optics_type, extract_optics_slice
20use MOM_unit_scaling, only : unit_scale_type
21use MOM_variables, only : thermo_var_ptrs
22use MOM_verticalGrid, only : verticalGrid_type
23
24implicit none ; private
25
26#include <MOM_memory.h>
27
28public bulkmixedlayer, bulkmixedlayer_init
29
30! A note on unit descriptions in comments: MOM6 uses units that can be rescaled for dimensional
31! consistency testing. These are noted in comments with units like Z, H, L, and T, along with
32! their mks counterparts with notation like "a velocity [Z T-1 ~> m s-1]". If the units
33! vary with the Boussinesq approximation, the Boussinesq variant is given first.
34
35!> The control structure with parameters for the MOM_bulk_mixed_layer module
36type, public :: bulkmixedlayer_CS ; private
37 logical :: initialized = .false. !< True if this control structure has been initialized.
38 integer :: nkml !< The number of layers in the mixed layer.
39 integer :: nkbl !< The number of buffer layers.
40 integer :: nsw !< The number of bands of penetrating shortwave radiation.
41 real :: mstar !< The ratio of the friction velocity cubed to the
42 !! TKE input to the mixed layer [nondim].
43 real :: nstar !< The fraction of the TKE input to the mixed layer
44 !! available to drive entrainment [nondim].
45 real :: nstar2 !< The fraction of potential energy released by
46 !! convective adjustment that drives entrainment [nondim].
47 logical :: absorb_all_SW !< If true, all shortwave radiation is absorbed by the
48 !! ocean, instead of passing through to the bottom mud.
49 real :: TKE_decay !< The ratio of the natural Ekman depth to the TKE
50 !! decay scale [nondim].
51 real :: bulk_Ri_ML !< The efficiency with which mean kinetic energy released by
52 !! mechanically forced entrainment of the mixed layer is
53 !! converted to TKE, times conversion factors between the
54 !! natural units of mean kinetic energy and TKE [Z2 L-2 ~> nondim]
55 real :: bulk_Ri_convective !< The efficiency with which convectively released mean kinetic
56 !! energy becomes TKE, times conversion factors between the natural
57 !! units of mean kinetic energy and TKE [Z2 L-2 ~> nondim]
58 real :: vonKar !< The von Karman constant as used for mixed layer viscosity [nondim]
59 real :: Hmix_min !< The minimum mixed layer thickness [H ~> m or kg m-2].
60 real :: mech_TKE_floor !< A tiny floor on the amount of turbulent kinetic energy that is
61 !! used when the mixed layer does not yet contain HMIX_MIN fluid
62 !! [H Z2 T-2 ~> m3 s-2 or J m-2]. The default is so small that its actual
63 !! value is irrelevant, but it is detectably greater than 0.
64 real :: H_limit_fluxes !< When the total ocean depth is less than this
65 !! value [H ~> m or kg m-2], scale away all surface forcing to
66 !! avoid boiling the ocean.
67 real :: ustar_min !< A minimum value of ustar to avoid numerical problems [Z T-1 ~> m s-1].
68 !! If the value is small enough, this should not affect the solution.
69 real :: omega !< The Earth's rotation rate [T-1 ~> s-1].
70 real :: dT_dS_wt !< When forced to extrapolate T & S to match the
71 !! layer densities, this factor [C S-1 ~> degC ppt-1] is
72 !! combined with the derivatives of density with T & S
73 !! to determines what direction is orthogonal to
74 !! density contours. It should be a typical value of
75 !! (dR/dS) / (dR/dT) in oceanic profiles.
76 !! 6 degC ppt-1 might be reasonable.
77 real :: Hbuffer_min !< The minimum buffer layer thickness when the mixed layer
78 !! is very large [H ~> m or kg m-2].
79 real :: Hbuffer_rel_min !< The minimum buffer layer thickness relative to the combined
80 !! mixed and buffer layer thicknesses when they are thin [nondim]
81 real :: BL_detrain_time !< A timescale that characterizes buffer layer detrainment
82 !! events [T ~> s].
83 real :: BL_extrap_lim !< A limit on the density range over which
84 !! extrapolation can occur when detraining from the
85 !! buffer layers, relative to the density range
86 !! within the mixed and buffer layers, when the
87 !! detrainment is going into the lightest interior
88 !! layer [nondim].
89 real :: BL_split_rho_tol !< The fractional tolerance for matching layer target densities
90 !! when splitting layers to deal with massive interior layers
91 !! that are lighter than one of the mixed or buffer layers [nondim].
92 logical :: ML_resort !< If true, resort the layers by density, rather than
93 !! doing convective adjustment.
94 integer :: ML_presort_nz_conv_adj !< If ML_resort is true, do convective
95 !! adjustment on this many layers (starting from the
96 !! top) before sorting the remaining layers.
97 real :: omega_frac !< When setting the decay scale for turbulence, use this fraction
98 !! of the absolute rotation rate blended with the local value of f,
99 !! as sqrt((1-of)*f^2 + of*4*omega^2) [nondim].
100 logical :: correct_absorption !< If true, the depth at which penetrating
101 !! shortwave radiation is absorbed is corrected by
102 !! moving some of the heating upward in the water
103 !! column. The default is false.
104 logical :: nonBous_energetics !< If true, use non-Boussinesq expressions for the energetic
105 !! calculations used in the bulk mixed layer calculations.
106 logical :: Resolve_Ekman !< If true, the nkml layers in the mixed layer are
107 !! chosen to optimally represent the impact of the
108 !! Ekman transport on the mixed layer TKE budget.
109 type(time_type), pointer :: Time => NULL() !< A pointer to the ocean model's clock.
110 logical :: TKE_diagnostics = .false. !< If true, calculate extensive diagnostics of the TKE budget
111 logical :: do_rivermix = .false. !< Provide additional TKE to mix river runoff
112 !! at the river mouths to rivermix_depth
113 real :: rivermix_depth = 0.0 !< The depth of mixing if do_rivermix is true [H ~> m or kg m-2].
114 logical :: limit_det !< If true, limit the extent of buffer layer
115 !! detrainment to be consistent with neighbors.
116 real :: lim_det_dH_sfc !< The fractional limit in the change between grid
117 !! points of the surface region (mixed & buffer
118 !! layer) thickness [nondim]. 0.5 by default.
119 real :: lim_det_dH_bathy !< The fraction of the total depth by which the
120 !! thickness of the surface region (mixed & buffer layers) is allowed
121 !! to change between grid points [nondim]. 0.2 by default.
122 logical :: use_river_heat_content !< If true, use the fluxes%runoff_Hflx field
123 !! to set the heat carried by runoff, instead of
124 !! using SST for temperature of liq_runoff
125 logical :: use_calving_heat_content !< Use SST for temperature of froz_runoff
126 logical :: convect_mom_bug !< If true, use code with a bug that causes a loss of momentum
127 !! conservation during mixedlayer convection.
128
129 type(diag_ctrl), pointer :: diag => NULL() !< A structure that is used to regulate the
130 !! timing of diagnostic output.
131 real :: Allowed_T_chg !< The amount by which temperature is allowed
132 !! to exceed previous values during detrainment [C ~> degC]
133 real :: Allowed_S_chg !< The amount by which salinity is allowed
134 !! to exceed previous values during detrainment [S ~> ppt]
135
136 ! These are terms in the mixed layer TKE budget, all in [H Z2 T-3 ~> m3 s-3 or W m-2] except as noted.
137 real, allocatable, dimension(:,:) :: &
138 ML_depth, & !< The mixed layer depth [H ~> m or kg m-2].
139 diag_TKE_wind, & !< The wind source of TKE [H Z2 T-3 ~> m3 s-3 or W m-2].
140 diag_TKE_RiBulk, & !< The resolved KE source of TKE [H Z2 T-3 ~> m3 s-3 or W m-2].
141 diag_TKE_conv, & !< The convective source of TKE [H Z2 T-3 ~> m3 s-3 or W m-2].
142 diag_TKE_pen_SW, & !< The TKE sink required to mix penetrating shortwave heating [H Z2 T-3 ~> m3 s-3 or W m-2].
143 diag_TKE_mech_decay, & !< The decay of mechanical TKE [H Z2 T-3 ~> m3 s-3 or W m-2].
144 diag_TKE_conv_decay, & !< The decay of convective TKE [H Z2 T-3 ~> m3 s-3 or W m-2].
145 diag_TKE_mixing, & !< The work done by TKE to deepen the mixed layer [H Z2 T-3 ~> m3 s-3 or W m-2].
146 diag_TKE_conv_s2, & !< The convective source of TKE due to to mixing in sigma2 [H Z2 T-3 ~> m3 s-3 or W m-2].
147 diag_PE_detrain, & !< The spurious source of potential energy due to mixed layer
148 !! detrainment [R Z3 T-3 ~> W m-2].
149 diag_PE_detrain2 !< The spurious source of potential energy due to mixed layer only
150 !! detrainment [R Z3 T-3 ~> W m-2].
151 type(group_pass_type) :: pass_h_sum_hmbl_prev !< For group halo pass
152
153 !>@{ Diagnostic IDs
154 integer :: id_ML_depth = -1, id_TKE_wind = -1, id_TKE_mixing = -1
155 integer :: id_TKE_RiBulk = -1, id_TKE_conv = -1, id_TKE_pen_SW = -1
156 integer :: id_TKE_mech_decay = -1, id_TKE_conv_decay = -1, id_TKE_conv_s2 = -1
157 integer :: id_PE_detrain = -1, id_PE_detrain2 = -1, id_h_mismatch = -1
158 integer :: id_Hsfc_used = -1, id_Hsfc_max = -1, id_Hsfc_min = -1
159 !>@}
160end type bulkmixedlayer_CS
161
162!>@{ CPU clock IDs
163integer :: id_clock_pass=0
164!>@}
165
166contains
167
168!> This subroutine partially steps the bulk mixed layer model.
169!! See \ref BML for more details.
1701subroutine bulkmixedlayer(h_3d, u_3d, v_3d, tv, fluxes, dt, ea, eb, G, GV, US, CS, &
1711 optics, BLD, H_ml, aggregate_FW_forcing, dt_diag, last_call)
172 type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
173 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
174 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
175 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
176 intent(inout) :: h_3d !< Layer thickness [H ~> m or kg m-2].
177 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
178 intent(in) :: u_3d !< Zonal velocities interpolated to h points
179 !! [L T-1 ~> m s-1].
180 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
181 intent(in) :: v_3d !< Zonal velocities interpolated to h points
182 !! [L T-1 ~> m s-1].
183 type(thermo_var_ptrs), intent(inout) :: tv !< A structure containing pointers to any
184 !! available thermodynamic fields. Absent
185 !! fields have NULL pointers.
186 type(forcing), intent(inout) :: fluxes !< A structure containing pointers to any
187 !! possible forcing fields. Unused fields
188 !! have NULL pointers.
189 real, intent(in) :: dt !< Time increment [T ~> s].
190 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
191 intent(inout) :: ea !< The amount of fluid moved downward into a
192 !! layer; this should be increased due to
193 !! mixed layer detrainment [H ~> m or kg m-2].
194 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
195 intent(inout) :: eb !< The amount of fluid moved upward into a
196 !! layer; this should be increased due to
197 !! mixed layer entrainment [H ~> m or kg m-2].
198 type(bulkmixedlayer_CS), intent(inout) :: CS !< Bulk mixed layer control structure
199 type(optics_type), pointer :: optics !< The structure that can be queried for the
200 !! inverse of the vertical absorption decay
201 !! scale for penetrating shortwave radiation.
202 real, dimension(SZI_(G),SZJ_(G)), &
203 intent(inout) :: BLD !< Active mixed layer depth [Z ~> m]
204 real, dimension(SZI_(G),SZJ_(G)), &
205 intent(inout) :: H_ml !< Active mixed layer thickness [H ~> m or kg m-2].
206 logical, intent(in) :: aggregate_FW_forcing !< If true, the net incoming and
207 !! outgoing surface freshwater fluxes are
208 !! combined before being applied, instead of
209 !! being applied separately.
210 real, optional, intent(in) :: dt_diag !< The diagnostic time step,
211 !! which may be less than dt if there are
212 !! two calls to mixedlayer [T ~> s].
213 logical, optional, intent(in) :: last_call !< if true, this is the last call
214 !! to mixedlayer in the current time step, so
215 !! diagnostics will be written. The default is
216 !! .true.
217
218 ! Local variables
219 real, dimension(SZI_(G),SZK_(GV)) :: &
2202 eaml, & ! The amount of fluid moved downward into a layer due to mixed
221 ! layer detrainment [H ~> m or kg m-2]. (I.e. entrainment from above.)
2222 ebml ! The amount of fluid moved upward into a layer due to mixed
223 ! layer detrainment [H ~> m or kg m-2]. (I.e. entrainment from below.)
224
225 ! If there is resorting, the vertical coordinate for these variables is the
226 ! new, sorted index space. Here layer 0 is an initially massless layer that
227 ! will be used to hold the new mixed layer properties.
228 real, dimension(SZI_(G),SZK0_(GV)) :: &
2292 h, & ! The layer thickness [H ~> m or kg m-2].
2302 T, & ! The layer temperatures [C ~> degC].
2312 S, & ! The layer salinities [S ~> ppt].
2322 R0, & ! The potential density referenced to the surface [R ~> kg m-3].
2332 SpV0, & ! The specific volume referenced to the surface [R-1 ~> m3 kg-1].
2342 Rcv ! The coordinate variable potential density [R ~> kg m-3].
235 real, dimension(SZI_(G),SZK_(GV)) :: &
2362 u, & ! The zonal velocity [L T-1 ~> m s-1].
2372 v, & ! The meridional velocity [L T-1 ~> m s-1].
2382 h_orig, & ! The original thickness [H ~> m or kg m-2].
2392 d_eb, & ! The downward increase across a layer in the entrainment from
240 ! below [H ~> m or kg m-2]. The sign convention is that positive values of
241 ! d_eb correspond to a gain in mass by a layer by upward motion.
2422 d_ea, & ! The upward increase across a layer in the entrainment from
243 ! above [H ~> m or kg m-2]. The sign convention is that positive values of
244 ! d_ea mean a net gain in mass by a layer from downward motion.
2452 eps ! The (small) thickness that must remain in a layer [H ~> m or kg m-2].
246 integer, dimension(SZI_(G),SZK_(GV)) :: &
2472 ksort ! The sorted k-index that each original layer goes to.
248 real, dimension(SZI_(G),SZJ_(G)) :: &
2492 h_miss ! The summed absolute mismatch [H ~> m or kg m-2].
250 real, dimension(SZI_(G),SZJ_(G)) :: &
2512 U_star_2d, &! The wind friction velocity, calculated using the Boussinesq reference density or
252 ! the time-evolving surface density in non-Boussinesq mode [Z T-1 ~> m s-1]
2532 U_star_H_2d ! The wind friction velocity in thickness-based units, calculated
254 ! using the Boussinesq reference density or the time-evolving
255 ! surface density in non-Boussinesq mode [H T-1 ~> m s-1 or kg m-2 s-1]
256 real, dimension(SZI_(G)) :: &
2572 TKE, & ! The turbulent kinetic energy available for mixing over a
258 ! time step [H Z2 T-2 ~> m3 s-2 or J m-2].
2592 Conv_En, & ! The turbulent kinetic energy source due to mixing down to
260 ! the depth of free convection [H Z2 T-2 ~> m3 s-2 or J m-2].
2612 htot, & ! The total depth of the layers being considered for
262 ! entrainment [H ~> m or kg m-2].
2632 R0_tot, & ! The integrated potential density referenced to the surface
264 ! of the layers which are fully entrained [H R ~> kg m-2 or kg2 m-5].
2652 SpV0_tot, & ! The integrated specific volume referenced to the surface
266 ! of the layers which are fully entrained [H R-1 ~> m4 kg-1 or m].
2672 Rcv_tot, & ! The integrated coordinate value potential density of the
268 ! layers that are fully entrained [H R ~> kg m-2 or kg2 m-5].
2692 Ttot, & ! The integrated temperature of layers which are fully
270 ! entrained [C H ~> degC m or degC kg m-2].
2712 Stot, & ! The integrated salt of layers which are fully entrained
272 ! [H S ~> m ppt or ppt kg m-2].
2732 uhtot, & ! The depth integrated zonal velocity in the mixed layer [H L T-1 ~> m2 s-1 or kg m-1 s-1]
2742 vhtot, & ! The depth integrated meridional velocity in the mixed layer [H L T-1 ~> m2 s-1 or kg m-1 s-1]
275
2762 netMassInOut, & ! The net mass flux (if non-Boussinesq) or volume flux (if
277 ! Boussinesq - i.e. the fresh water flux (P+R-E)) into the
278 ! ocean over a time step [H ~> m or kg m-2].
2792 NetMassOut, & ! The mass flux (if non-Boussinesq) or volume flux (if Boussinesq)
280 ! over a time step from evaporating fresh water [H ~> m or kg m-2]
2812 Net_heat, & ! The net heating at the surface over a time step [C H ~> degC m or degC kg m-2]
282 ! Any penetrating shortwave radiation is not included in Net_heat.
2832 Net_salt, & ! The surface salt flux into the ocean over a time step [S H ~> ppt m or ppt kg m-2]
2842 Idecay_len_TKE, & ! The inverse of a turbulence decay length scale [H-1 ~> m-1 or m2 kg-1].
2852 p_ref, & ! Reference pressure for the potential density governing mixed
286 ! layer dynamics, almost always 0 (or 1e5) [R L2 T-2 ~> Pa].
2872 p_ref_cv, & ! Reference pressure for the potential density which defines
288 ! the coordinate variable, set to P_Ref [R L2 T-2 ~> Pa].
2892 dR0_dT, & ! Partial derivative of the mixed layer potential density with
290 ! temperature [R C-1 ~> kg m-3 degC-1].
2912 dSpV0_dT, & ! Partial derivative of the mixed layer specific volume with
292 ! temperature [R-1 C-1 ~> m3 kg-1 degC-1].
2932 dRcv_dT, & ! Partial derivative of the coordinate variable potential
294 ! density in the mixed layer with temperature [R C-1 ~> kg m-3 degC-1].
2952 dR0_dS, & ! Partial derivative of the mixed layer potential density with
296 ! salinity [R S-1 ~> kg m-3 ppt-1].
2972 dSpV0_dS, & ! Partial derivative of the mixed layer specific volume with
298 ! salinity [R-1 S-1 ~> m3 kg-1 ppt-1].
2992 dRcv_dS, & ! Partial derivative of the coordinate variable potential
300 ! density in the mixed layer with salinity [R S-1 ~> kg m-3 ppt-1].
3012 p_sfc, & ! The sea surface pressure [R L2 T-2 ~> Pa]
3022 dp_ml, & ! The pressure change across the mixed layer [R L2 T-2 ~> Pa]
3032 SpV_ml, & ! The specific volume averaged across the mixed layer [R-1 ~> m3 kg-1]
3042 TKE_river ! The source of turbulent kinetic energy available for mixing
305 ! at rivermouths [H Z2 T-3 ~> m3 s-3 or W m-2].
306
307 real, dimension(max(CS%nsw,1),SZI_(G)) :: &
3082 Pen_SW_bnd ! The penetrating fraction of the shortwave heating integrated
309 ! over a time step in each band [C H ~> degC m or degC kg m-2].
310 real, dimension(max(CS%nsw,1),SZI_(G),SZK_(GV)) :: &
3112 opacity_band ! The opacity in each band [H-1 ~> m-1 or m2 kg-1]. The indices are band, i, k.
312
3131 real :: cMKE(2,SZI_(G)) ! Coefficients of HpE and HpE^2 used in calculating the
314 ! denominator of MKE_rate; the two elements have differing
315 ! units of [H-1 ~> m-1 or m2 kg-1] and [H-2 ~> m-2 or m4 kg-2].
316 real :: Irho0 ! 1.0 / rho_0 [R-1 ~> m3 kg-1]
317 real :: Inkml, Inkmlm1! 1.0 / REAL(nkml) and 1.0 / REAL(nkml-1) [nondim]
318 real :: Ih ! The inverse of a thickness [H-1 ~> m-1 or m2 kg-1].
319 real :: Idt_diag ! The inverse of the timestep used for diagnostics [T-1 ~> s-1].
320 real :: RmixConst ! A combination of constants used in the river mixing energy
321 ! calculation [H Z T-2 R-2 ~> m8 s-2 kg-2 or m5 s-2 kg-1] or
322 ! [H Z T-2 ~> m2 s-2 or kg m-1 s-2]
323 real, dimension(SZI_(G)) :: &
3242 dKE_FC, & ! The change in mean kinetic energy due to free convection
325 ! [H Z2 T-2 ~> m3 s-2 or J m-2].
3262 h_CA ! The depth to which convective adjustment has gone [H ~> m or kg m-2].
327 real, dimension(SZI_(G),SZK_(GV)) :: &
3282 dKE_CA, & ! The change in mean kinetic energy due to convective
329 ! adjustment [H Z2 T-2 ~> m3 s-2 or J m-2].
3302 cTKE ! The turbulent kinetic energy source due to convective
331 ! adjustment [H Z2 T-2 ~> m3 s-2 or J m-2].
332 real, dimension(SZI_(G),SZJ_(G)) :: &
3332 Hsfc_max, & ! The thickness of the surface region (mixed and buffer layers)
334 ! after entrainment but before any buffer layer detrainment [H ~> m or kg m-2].
3352 Hsfc_used, & ! The thickness of the surface region after buffer layer
336 ! detrainment [H ~> m or kg m-2].
3372 Hsfc_min, & ! The minimum thickness of the surface region based on the
338 ! new mixed layer depth and the previous thickness of the
339 ! neighboring water columns [H ~> m or kg m-2].
3402 h_sum, & ! The total thickness of the water column [H ~> m or kg m-2].
3412 hmbl_prev ! The previous thickness of the mixed and buffer layers [H ~> m or kg m-2].
342 real, dimension(SZI_(G)) :: &
3432 Hsfc, & ! The thickness of the surface region (mixed and buffer
344 ! layers before detrainment in to the interior [H ~> m or kg m-2].
3451 max_BL_det ! If non-negative, the maximum amount of entrainment from
346 ! the buffer layers that will be allowed this time step [H ~> m or kg m-2].
347 real :: dHsfc, dHD ! Local copies of nondimensional parameters [nondim]
348 real :: H_nbr ! A minimum thickness based on neighboring thicknesses [H ~> m or kg m-2].
349
350 real :: absf_x_H ! The absolute value of f times the mixed layer thickness [H T-1 ~> m s-1 or kg m-2 s-1].
351 real :: kU_star ! Ustar times the Von Karman constant [H T-1 ~> m s-1 or kg m-2 s-1].
352 real :: dt__diag ! A rescaled copy of dt_diag (if present) or dt [T ~> s].
353 logical :: write_diags ! If true, write out diagnostics with this step.
354 logical :: reset_diags ! If true, zero out the accumulated diagnostics.
355 integer, dimension(2) :: EOSdom ! The i-computational domain for the equation of state
356 integer :: i, j, k, is, ie, js, je, nz, nkmb
357 integer :: nsw ! The number of bands of penetrating shortwave radiation.
358
3591 is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke
360
3611 if (.not. CS%initialized) call MOM_error(FATAL, "MOM_bulk_mixed_layer: "//&
3620 "Module must be initialized before it is used.")
3631 if (GV%nkml < 1) return
364
3651 if (.not. associated(tv%eqn_of_state)) call MOM_error(FATAL, &
366 "MOM_mixed_layer: Temperature, salinity and an equation of state "//&
3670 "must now be used.")
3681 if (.not. (associated(fluxes%ustar) .or. associated(fluxes%tau_mag))) call MOM_error(FATAL, &
3690 "MOM_mixed_layer: No surface TKE fluxes (ustar or tau_mag) defined in mixedlayer!")
370
3711 nkmb = CS%nkml+CS%nkbl
3721 Inkml = 1.0 / REAL(CS%nkml)
3731 if (CS%nkml > 1) Inkmlm1 = 1.0 / REAL(CS%nkml-1)
374
3751 Irho0 = 1.0 / GV%Rho0
3761 dt__diag = dt ; if (present(dt_diag)) dt__diag = dt_diag
3771 Idt_diag = 1.0 / dt__diag
3781 write_diags = .true. ; if (present(last_call)) write_diags = last_call
379
380737 p_ref(:) = 0.0 ; p_ref_cv(:) = tv%P_Ref
381
3821 nsw = CS%nsw
383
3841 if (CS%limit_det .or. (CS%id_Hsfc_min > 0)) then
385 !$OMP parallel do default(shared)
38666067 do j=js-1,je+1 ; do i=is-1,ie+1
38766066 h_sum(i,j) = 0.0 ; hmbl_prev(i,j) = 0.0
388 enddo ; enddo
389 !$OMP parallel do default(shared)
390183 do j=js-1,je+1
391264446 do k=1,nkmb ; do i=is-1,ie+1
392263536 h_sum(i,j) = h_sum(i,j) + h_3d(i,j,k)
393264264 hmbl_prev(i,j) = hmbl_prev(i,j) + h_3d(i,j,k)
394 enddo ; enddo
3951189371 do k=nkmb+1,nz ; do i=is-1,ie+1
3961189188 h_sum(i,j) = h_sum(i,j) + h_3d(i,j,k)
397 enddo ; enddo
398 enddo
399
4001 call cpu_clock_begin(id_clock_pass)
4011 call create_group_pass(CS%pass_h_sum_hmbl_prev, h_sum,G%Domain)
4021 call create_group_pass(CS%pass_h_sum_hmbl_prev, hmbl_prev,G%Domain)
4031 call do_group_pass(CS%pass_h_sum_hmbl_prev, G%Domain)
4041 call cpu_clock_end(id_clock_pass)
405 endif
406
407 ! Determine whether to zero out diagnostics before accumulation.
4081 reset_diags = .true.
4091 if (present(dt_diag) .and. write_diags .and. (dt__diag > dt)) &
4100 reset_diags = .false. ! This is the second call to mixedlayer.
411
4121 if (reset_diags) then
4131 if (CS%TKE_diagnostics) then
414 !$OMP parallel do default(shared)
4150 do j=js,je ; do i=is,ie
4160 CS%diag_TKE_wind(i,j) = 0.0 ; CS%diag_TKE_RiBulk(i,j) = 0.0
4170 CS%diag_TKE_conv(i,j) = 0.0 ; CS%diag_TKE_pen_SW(i,j) = 0.0
4180 CS%diag_TKE_mixing(i,j) = 0.0 ; CS%diag_TKE_mech_decay(i,j) = 0.0
4190 CS%diag_TKE_conv_decay(i,j) = 0.0 ; CS%diag_TKE_conv_s2(i,j) = 0.0
420 enddo ; enddo
421 endif
4221 if (allocated(CS%diag_PE_detrain)) then
423 !$OMP parallel do default(shared)
4240 do j=js,je ; do i=is,ie
4250 CS%diag_PE_detrain(i,j) = 0.0
426 enddo ; enddo
427 endif
4281 if (allocated(CS%diag_PE_detrain2)) then
429 !$OMP parallel do default(shared)
4300 do j=js,je ; do i=is,ie
4310 CS%diag_PE_detrain2(i,j) = 0.0
432 enddo ; enddo
433 endif
434 endif
435
4361 if (CS%ML_resort) then
4370 do i=is,ie ; h_CA(i) = 0.0 ; enddo
4380 do k=1,nz ; do i=is,ie ; dKE_CA(i,k) = 0.0 ; cTKE(i,k) = 0.0 ; enddo ; enddo
439 endif
440369 max_BL_det(:) = -1
4411 EOSdom(:) = EOS_domain(G%HI)
442
443 ! Extract the friction velocity from the forcing type.
4441 call find_ustar(fluxes, tv, U_star_2d, G, GV, US)
4451 if (CS%Resolve_Ekman .and. (CS%nkml>1)) &
4460 call find_ustar(fluxes, tv, U_star_H_2d, G, GV, US, H_T_units=.true.)
447
448 !$OMP parallel default(shared) firstprivate(dKE_CA,cTKE,h_CA,max_BL_det,p_ref,p_ref_cv) &
449 !$OMP private(h,u,v,h_orig,eps,T,S,opacity_band,d_ea,d_eb,R0,SpV0,Rcv,ksort, &
450 !$OMP dR0_dT,dR0_dS,dRcv_dT,dRcv_dS,dSpV0_dT,dSpV0_dS,htot,Ttot,Stot,TKE,Conv_en, &
451 !$OMP RmixConst,TKE_river,Pen_SW_bnd,netMassInOut,NetMassOut, &
452 !$OMP Net_heat,Net_salt,uhtot,vhtot,R0_tot,Rcv_tot,SpV0_tot,dKE_FC, &
453 !$OMP Idecay_len_TKE,cMKE,Hsfc,dHsfc,dHD,H_nbr,kU_Star, &
454 !$OMP absf_x_H,ebml,eaml)
455 !$OMP do
456181 do j=js,je
457 ! Copy the thicknesses and other fields to 2-d arrays.
4581429740 do k=1,nz ; do i=is,ie
4591425600 h(i,k) = h_3d(i,j,k) ; u(i,k) = u_3d(i,j,k) ; v(i,k) = v_3d(i,j,k)
4601425600 h_orig(i,k) = h_3d(i,j,k)
4611425600 eps(i,k) = 0.0 ; if (k > nkmb) eps(i,k) = GV%Angstrom_H
4621429560 T(i,k) = tv%T(i,j,k) ; S(i,k) = tv%S(i,j,k)
463 enddo ; enddo
464180 if (nsw>0) then
465180 if (GV%Boussinesq .or. (.not.allocated(tv%SpV_avg))) then
466180 call extract_optics_slice(optics, j, G, GV, opacity=opacity_band, opacity_scale=GV%H_to_Z)
467 else
468 call extract_optics_slice(optics, j, G, GV, opacity=opacity_band, opacity_scale=GV%H_to_RZ, &
4690 SpV_avg=tv%SpV_avg)
470 endif
471 endif
472
4731429740 do k=1,nz ; do i=is,ie
4741429560 d_ea(i,k) = 0.0 ; d_eb(i,k) = 0.0
475 enddo ; enddo
476
477 ! Calculate an estimate of the mid-mixed layer pressure [R L2 T-2 ~> Pa]
478180 if (associated(tv%p_surf)) then
47964980 do i=is,ie ; p_ref(i) = tv%p_surf(i,j) ; enddo
480 else
4810 do i=is,ie ; p_ref(i) = 0.0 ; enddo
482 endif
483130140 do k=1,CS%nkml ; do i=is,ie
484129960 p_ref(i) = p_ref(i) + 0.5*(GV%H_to_RZ*GV%g_Earth)*h(i,k)
485 enddo ; enddo
486180 if (CS%nonBous_energetics) then
4870 call calculate_specific_vol_derivs(T(:,1), S(:,1), p_ref, dSpV0_dT, dSpV0_dS, tv%eqn_of_state, EOSdom)
4880 do k=1,nz
4890 call calculate_spec_vol(T(:,k), S(:,k), p_ref, SpV0(:,k), tv%eqn_of_state, EOSdom)
490 enddo
491 else
492180 call calculate_density_derivs(T(:,1), S(:,1), p_ref, dR0_dT, dR0_dS, tv%eqn_of_state, EOSdom)
4934140 do k=1,nz
4944140 call calculate_density(T(:,k), S(:,k), p_ref, R0(:,k), tv%eqn_of_state, EOSdom)
495 enddo
496 endif
497180 call calculate_density_derivs(T(:,1), S(:,1), p_ref_cv, dRcv_dT, dRcv_dS, tv%eqn_of_state, EOSdom)
4984140 do k=1,nz
4994140 call calculate_density(T(:,k), S(:,k), p_ref_cv, Rcv(:,k), tv%eqn_of_state, EOSdom)
500 enddo
501
502180 if (CS%ML_resort) then
5030 if (CS%ML_presort_nz_conv_adj > 0) &
504 call convective_adjustment(h, u, v, R0, SpV0, Rcv, T, S, eps, d_eb, dKE_CA, cTKE, j, G, GV, &
5050 US, CS, CS%ML_presort_nz_conv_adj)
506
5070 call sort_ML(h, R0, SpV0, eps, G, GV, CS, ksort)
508 else
5091429740 do k=1,nz ; do i=is,ie ; ksort(i,k) = k ; enddo ; enddo
510
511 ! Undergo instantaneous entrainment into the buffer layers and mixed layers
512 ! to remove hydrostatic instabilities. Any water that is lighter than
513 ! currently in the mixed or buffer layer is entrained.
514180 call convective_adjustment(h, u, v, R0, SpV0, Rcv, T, S, eps, d_eb, dKE_CA, cTKE, j, G, GV, US, CS)
51564980 do i=is,ie ; h_CA(i) = h(i,1) ; enddo
516
517 endif
518
519180 if (associated(fluxes%lrunoff) .and. CS%do_rivermix) then
520
521 ! Here we add an additional source of TKE to the mixed layer where river
522 ! is present to simulate unresolved estuaries. The TKE input is diagnosed
523 ! as follows:
524 ! TKE_river[H Z2 T-3 ~> m3 s-3] = 0.5*rivermix_depth * g * Irho0**2 * drho_ds *
525 ! River*(Samb - Sriver) = CS%mstar*U_star^3
526 ! where River is in units of [R Z T-1 ~> kg m-2 s-1].
527 ! Samb = Ambient salinity at the mouth of the estuary
528 ! rivermix_depth = The prescribed depth over which to mix river inflow
529 ! drho_ds = The gradient of density wrt salt at the ambient surface salinity.
530 ! Sriver = 0 (i.e. rivers are assumed to be pure freshwater)
5310 if (CS%nonBous_energetics) then
5320 RmixConst = -0.5*CS%rivermix_depth * GV%g_Earth_Z_T2
5330 do i=is,ie
534 TKE_river(i) = max(0.0, RmixConst * dSpV0_dS(i) * &
535 ((fluxes%lrunoff(i,j) + fluxes%frunoff(i,j)) + &
5360 (fluxes%lrunoff_glc(i,j) + fluxes%frunoff_glc(i,j))) * S(i,1))
537 enddo
538 else
5390 RmixConst = 0.5*CS%rivermix_depth * GV%g_Earth_Z_T2 * Irho0**2
5400 do i=is,ie
541 TKE_river(i) = max(0.0, RmixConst*dR0_dS(i)* &
542 ((fluxes%lrunoff(i,j) + fluxes%frunoff(i,j)) + &
5430 (fluxes%lrunoff_glc(i,j) + fluxes%frunoff_glc(i,j))) * S(i,1))
544 enddo
545 endif
546 else
54764980 do i=is,ie ; TKE_river(i) = 0.0 ; enddo
548 endif
549
550 ! The surface forcing is contained in the fluxes type.
551 ! We aggregate the thermodynamic forcing for a time step into the following:
552 ! netMassInOut = water [H ~> m or kg m-2] added/removed via surface fluxes
553 ! netMassOut = water [H ~> m or kg m-2] removed via evaporating surface fluxes
554 ! net_heat = heat via surface fluxes [C H ~> degC m or degC kg m-2]
555 ! net_salt = salt via surface fluxes [S H ~> ppt m or gSalt m-2]
556 ! Pen_SW_bnd = components to penetrative shortwave radiation
557 call extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, &
558 CS%H_limit_fluxes, CS%use_river_heat_content, CS%use_calving_heat_content, &
559 h(:,1:), T(:,1:), netMassInOut, netMassOut, Net_heat, Net_salt, Pen_SW_bnd, &
560180 tv, aggregate_FW_forcing)
561
562 ! This subroutine causes the mixed layer to entrain to depth of free convection.
563 call mixedlayer_convection(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, R0_tot, SpV0_tot, Rcv_tot, &
564 u, v, T, S, R0, SpV0, Rcv, eps, dR0_dT, dSpV0_dT, dRcv_dT, dR0_dS, dSpV0_dS, dRcv_dS, &
565 netMassInOut, netMassOut, Net_heat, Net_salt, &
566 nsw, Pen_SW_bnd, opacity_band, Conv_En, dKE_FC, &
567180 j, ksort, G, GV, US, CS, tv, fluxes, dt, aggregate_FW_forcing)
568
569 ! Now the mixed layer undergoes mechanically forced entrainment.
570 ! The mixed layer may entrain down to the Monin-Obukhov depth if the
571 ! surface is becoming lighter, and is effectively detraining.
572
573 ! First the TKE at the depth of free convection that is available
574 ! to drive mixing is calculated.
575 call find_starting_TKE(htot, h_CA, fluxes, U_star_2d, Conv_En, cTKE, dKE_FC, dKE_CA, &
576 TKE, TKE_river, Idecay_len_TKE, cMKE, tv, dt, Idt_diag, &
577180 j, ksort, G, GV, US, CS)
578
579 ! Here the mechanically driven entrainment occurs.
580 call mechanical_entrainment(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, &
581 R0_tot, SpV0_tot, Rcv_tot, u, v, T, S, R0, SpV0, Rcv, eps, &
582 dR0_dT, dSpV0_dT, dRcv_dT, cMKE, Idt_diag, nsw, Pen_SW_bnd, &
583180 opacity_band, TKE, Idecay_len_TKE, j, ksort, G, GV, US, CS)
584
585 call absorbRemainingSW(G, GV, US, h(:,1:), opacity_band, nsw, optics, j, dt, &
586 CS%H_limit_fluxes, CS%correct_absorption, CS%absorb_all_SW, &
587180 T(:,1:), Pen_SW_bnd, eps, ksort, htot, Ttot)
588
589180 if (CS%TKE_diagnostics) then ; do i=is,ie
5900 CS%diag_TKE_mech_decay(i,j) = CS%diag_TKE_mech_decay(i,j) - Idt_diag * TKE(i)
591 enddo ; endif
592
593 ! Calculate the homogeneous mixed layer properties and store them in layer 0.
59464980 do i=is,ie ; if (htot(i) > 0.0) then
59564800 Ih = 1.0 / htot(i)
59664800 if (CS%nonBous_energetics) then
5970 SpV0(i,0) = SpV0_tot(i) * Ih
598 else
59964800 R0(i,0) = R0_tot(i) * Ih
600 endif
60164800 Rcv(i,0) = Rcv_tot(i) * Ih
60264800 T(i,0) = Ttot(i) * Ih ; S(i,0) = Stot(i) * Ih
60364800 h(i,0) = htot(i)
604 else ! This may not ever be needed?
6050 T(i,0) = T(i,1) ; S(i,0) = S(i,1) ; Rcv(i,0) = Rcv(i,1)
6060 if (CS%nonBous_energetics) then
6070 SpV0(i,0) = SpV0(i,1)
608 else
6090 R0(i,0) = R0(i,1)
610 endif
6110 h(i,0) = htot(i)
612 endif ; enddo
613180 if (write_diags .and. allocated(CS%ML_depth)) then ; do i=is,ie
6140 CS%ML_depth(i,j) = h(i,0) ! Store the diagnostic.
615 enddo ; endif
616
617 ! Return the mixed layer depth in [Z ~> m].
618180 if (GV%Boussinesq .or. GV%semi_Boussinesq) then
61964980 do i=is,ie
62064980 BLD(i,j) = G%mask2dT(i,j) * GV%H_to_Z*h(i,0)
621 enddo
622 else
6230 do i=is,ie ; dp_ml(i) = GV%g_Earth * GV%H_to_RZ * h(i,0) ; enddo
6240 if (associated(tv%p_surf)) then
6250 do i=is,ie ; p_sfc(i) = tv%p_surf(i,j) ; enddo
626 else
6270 do i=is,ie ; p_sfc(i) = 0.0 ; enddo
628 endif
6290 call average_specific_vol(T(:,0), S(:,0), p_sfc, dp_ml, SpV_ml, tv%eqn_of_state)
6300 do i=is,ie
6310 BLD(i,j) = G%mask2dT(i,j) * GV%H_to_RZ * SpV_ml(i) * h(i,0)
632 enddo
633 endif
634 ! Return the mixed layer thickness in [H ~> m or kg m-2].
63564980 do i=is,ie
63664980 H_ml(i,j) = G%mask2dT(i,j) * h(i,0)
637 enddo
638
639! At this point, return water to the original layers, but constrained to
640! still be sorted. After this point, all the water that is in massive
641! interior layers will be denser than water remaining in the mixed- and
642! buffer-layers. To achieve this, some of these variable density layers
643! might be split between two isopycnal layers that are denser than new
644! mixed layer or any remaining water from the old mixed- or buffer-layers.
645! Alternately, if there are fewer than nkbl of the old buffer or mixed layers
646! with any mass, relatively light interior layers might be transferred to
647! these unused layers (but not currently in the code).
648
649180 if (CS%ML_resort) then
650 call resort_ML(h(:,0:), T(:,0:), S(:,0:), R0(:,0:), SpV0(:,0:), Rcv(:,0:), GV%Rlay(:), eps, &
6510 d_ea, d_eb, ksort, G, GV, CS, dR0_dT, dR0_dS, dSpV0_dT, dSpV0_dS, dRcv_dT, dRcv_dS)
652 endif
653
654180 if (CS%limit_det .or. (CS%id_Hsfc_max > 0) .or. (CS%id_Hsfc_min > 0)) then
65564980 do i=is,ie ; Hsfc(i) = h(i,0) ; enddo
656260100 do k=1,nkmb ; do i=is,ie ; Hsfc(i) = Hsfc(i) + h(i,k) ; enddo ; enddo
657
658180 if (CS%limit_det .or. (CS%id_Hsfc_min > 0)) then
659180 dHsfc = CS%lim_det_dH_sfc ; dHD = CS%lim_det_dH_bathy
66064980 do i=is,ie
661 H_nbr = min(dHsfc*max(hmbl_prev(i-1,j), hmbl_prev(i+1,j), &
662 hmbl_prev(i,j-1), hmbl_prev(i,j+1)), &
663 max(hmbl_prev(i-1,j) - dHD*min(h_sum(i,j),h_sum(i-1,j)), &
664 hmbl_prev(i+1,j) - dHD*min(h_sum(i,j),h_sum(i+1,j)), &
665 hmbl_prev(i,j-1) - dHD*min(h_sum(i,j),h_sum(i,j-1)), &
66664800 hmbl_prev(i,j+1) - dHD*min(h_sum(i,j),h_sum(i,j+1))) )
667
66864800 Hsfc_min(i,j) = max(h(i,0), min(Hsfc(i), H_nbr))
669
67064980 if (CS%limit_det) max_BL_det(i) = max(0.0, Hsfc(i)-H_nbr)
671 enddo
672 endif
673
674180 if (CS%id_Hsfc_max > 0) then ; do i=is,ie
6750 Hsfc_max(i,j) = Hsfc(i)
676 enddo ; endif
677 endif
678
679 ! Move water left in the former mixed layer into the buffer layer and
680 ! from the buffer layer into the interior. These steps might best be
681 ! treated in conjunction.
682180 if (CS%nkbl == 1) then
683 call mixedlayer_detrain_1(h(:,0:), T(:,0:), S(:,0:), R0(:,0:), SpV0(:,0:), Rcv(:,0:), &
684 GV%Rlay(:), dt, dt__diag, d_ea, d_eb, j, G, GV, US, CS, &
6850 dRcv_dT, dRcv_dS, max_BL_det)
686180 elseif (CS%nkbl == 2) then
687 call mixedlayer_detrain_2(h(:,0:), T(:,0:), S(:,0:), R0(:,0:), SpV0(:,0:), Rcv(:,0:), &
688 GV%Rlay(:), dt, dt__diag, d_ea, j, G, GV, US, CS, &
689180 dR0_dT, dR0_dS, dSpV0_dT, dSpV0_dS, dRcv_dT, dRcv_dS, max_BL_det)
690 else ! CS%nkbl not = 1 or 2
691 ! This code only works with 1 or 2 buffer layers.
6920 call MOM_error(FATAL, "MOM_mixed_layer: CS%nkbl must be 1 or 2 for now.")
693 endif
694
695180 if (CS%id_Hsfc_used > 0) then
6960 do i=is,ie ; Hsfc_used(i,j) = h(i,0) ; enddo
6970 do k=CS%nkml+1,nkmb ; do i=is,ie
6980 Hsfc_used(i,j) = Hsfc_used(i,j) + h(i,k)
699 enddo ; enddo
700 endif
701
702! Now set the properties of the layers in the mixed layer in the original
703! 3-d variables.
704180 if (CS%Resolve_Ekman .and. (CS%nkml>1)) then
705 ! The thickness of the topmost piece of the mixed layer is given by
706 ! h_1 = H / (3 + sqrt(|f|*H^2/2*nu_max)), which asymptotes to the Ekman
707 ! layer depth and 1/3 of the mixed layer depth. This curve has been
708 ! determined to maximize the impact of the Ekman transport in the mixed
709 ! layer TKE budget with nkml=2. With nkml=3, this should also be used,
710 ! as the third piece will then optimally describe mixed layer
711 ! restratification. For nkml>=4 the whole strategy should be revisited.
7120 do i=is,ie
713 ! Perhaps in the following, u* could be replaced with u*+w*?
7140 kU_star = CS%vonKar * U_star_H_2d(i,j)
7150 if (associated(fluxes%ustar_shelf) .and. associated(fluxes%frac_shelf_h)) then
7160 if (fluxes%frac_shelf_h(i,j) > 0.0) then
7170 if (allocated(tv%SpV_avg)) then
718 kU_star = (1.0 - fluxes%frac_shelf_h(i,j)) * kU_star + &
719 fluxes%frac_shelf_h(i,j) * ((CS%vonKar*fluxes%ustar_shelf(i,j)) / &
7200 (GV%H_to_RZ * tv%SpV_avg(i,j,1)))
721 else
722 kU_star = (1.0 - fluxes%frac_shelf_h(i,j)) * kU_star + &
7230 fluxes%frac_shelf_h(i,j) * (CS%vonKar*GV%Z_to_H*fluxes%ustar_shelf(i,j))
724 endif
725 endif
726 endif
727 absf_x_H = 0.25 * h(i,0) * &
728 ((abs(G%CoriolisBu(I,J)) + abs(G%CoriolisBu(I-1,J-1))) + &
7290 (abs(G%CoriolisBu(I,J-1)) + abs(G%CoriolisBu(I-1,J))))
730 ! If the mixed layer vertical viscosity specification is changed in
731 ! MOM_vert_friction.F90, this line will have to be modified accordingly.
7320 h_3d(i,j,1) = h(i,0) / (3.0 + sqrt(absf_x_H*(absf_x_H + 2.0*kU_star) / kU_star**2))
7330 do k=2,CS%nkml
734 ! The other layers are evenly distributed through the mixed layer.
7350 h_3d(i,j,k) = (h(i,0)-h_3d(i,j,1)) * Inkmlm1
7360 d_ea(i,k) = d_ea(i,k) + h_3d(i,j,k)
7370 d_ea(i,1) = d_ea(i,1) - h_3d(i,j,k)
738 enddo
739 enddo
740 else
74164980 do i=is,ie
74264980 h_3d(i,j,1) = h(i,0) * Inkml
743 enddo
74465160 do k=2,CS%nkml ; do i=is,ie
74564800 h_3d(i,j,k) = h(i,0) * Inkml
74664800 d_ea(i,k) = d_ea(i,k) + h_3d(i,j,k)
74764980 d_ea(i,1) = d_ea(i,1) - h_3d(i,j,k)
748 enddo ; enddo
749 endif
75064980 do i=is,ie ; h(i,0) = 0.0 ; enddo
751130140 do k=1,CS%nkml ; do i=is,ie
752129960 tv%T(i,j,k) = T(i,0) ; tv%S(i,j,k) = S(i,0)
753 enddo ; enddo
754
755 ! These sum needs to be done in the original layer space.
756
757 ! The treatment of layer 1 is atypical because evaporation shows up as
758 ! negative ea(i,1), and because all precipitation goes straight into layer 1.
759 ! The code is ordered so that any roundoff errors in ea are lost the surface.
760! do i=is,ie ; eaml(i,1) = 0.0 ; enddo
761! do k=2,nz ; do i=is,ie ; eaml(i,k) = eaml(i,k-1) - d_ea(i,k-1) ; enddo ; enddo
762! do i=is,ie ; eaml(i,1) = netMassInOut(i) ; enddo
763
764
76564980 do i=is,ie
766! eaml(i,nz) is derived from h(i,nz) - h_orig(i,nz) = eaml(i,nz) - ebml(i,nz-1)
76764800 ebml(i,nz) = 0.0
76864980 eaml(i,nz) = (h(i,nz) - h_orig(i,nz)) - d_eb(i,nz)
769 enddo
7701364760 do k=nz-1,1,-1 ; do i=is,ie
7711360800 ebml(i,k) = ebml(i,k+1) - d_eb(i,k+1)
7721364580 eaml(i,k) = eaml(i,k+1) + d_ea(i,k)
773 enddo ; enddo
77464980 do i=is,ie ; eaml(i,1) = netMassInOut(i) ; enddo
775
776 ! Copy the interior thicknesses and other fields back to the 3-d arrays.
7771299780 do k=CS%nkml+1,nz ; do i=is,ie
7781299600 h_3d(i,j,k) = h(i,k) ; tv%T(i,j,k) = T(i,k) ; tv%S(i,j,k) = S(i,k)
779 enddo ; enddo
780
7811429740 do k=1,nz ; do i=is,ie
7821425600 ea(i,j,k) = ea(i,j,k) + eaml(i,k)
7831429560 eb(i,j,k) = eb(i,j,k) + ebml(i,k)
784 enddo ; enddo
785
786181 if (CS%id_h_mismatch > 0) then
7870 do i=is,ie
788 h_miss(i,j) = abs(h_3d(i,j,1) - (h_orig(i,1) + &
7890 (eaml(i,1) + (ebml(i,1) - eaml(i,1+1)))))
790 enddo
7910 do k=2,nz-1 ; do i=is,ie
792 h_miss(i,j) = h_miss(i,j) + abs(h_3d(i,j,k) - (h_orig(i,k) + &
7930 ((eaml(i,k) - ebml(i,k-1)) + (ebml(i,k) - eaml(i,k+1)))))
794 enddo ; enddo
7950 do i=is,ie
796 h_miss(i,j) = h_miss(i,j) + abs(h_3d(i,j,nz) - (h_orig(i,nz) + &
7970 ((eaml(i,nz) - ebml(i,nz-1)) + ebml(i,nz))))
798 enddo
799 endif
800
801 enddo ! j loop
802 !$OMP end parallel
803
804 ! Whenever thickness changes let the diag manager know, target grids
805 ! for vertical remapping may need to be regenerated.
806 ! This needs to happen after the H update and before the next post_data.
8071 call diag_update_remap_grids(CS%diag)
808
809
8101 if (write_diags) then
8111 if (CS%id_ML_depth > 0) &
8120 call post_data(CS%id_ML_depth, CS%ML_depth, CS%diag)
8131 if (CS%id_TKE_wind > 0) &
8140 call post_data(CS%id_TKE_wind, CS%diag_TKE_wind, CS%diag)
8151 if (CS%id_TKE_RiBulk > 0) &
8160 call post_data(CS%id_TKE_RiBulk, CS%diag_TKE_RiBulk, CS%diag)
8171 if (CS%id_TKE_conv > 0) &
8180 call post_data(CS%id_TKE_conv, CS%diag_TKE_conv, CS%diag)
8191 if (CS%id_TKE_pen_SW > 0) &
8200 call post_data(CS%id_TKE_pen_SW, CS%diag_TKE_pen_SW, CS%diag)
8211 if (CS%id_TKE_mixing > 0) &
8220 call post_data(CS%id_TKE_mixing, CS%diag_TKE_mixing, CS%diag)
8231 if (CS%id_TKE_mech_decay > 0) &
8240 call post_data(CS%id_TKE_mech_decay, CS%diag_TKE_mech_decay, CS%diag)
8251 if (CS%id_TKE_conv_decay > 0) &
8260 call post_data(CS%id_TKE_conv_decay, CS%diag_TKE_conv_decay, CS%diag)
8271 if (CS%id_TKE_conv_s2 > 0) &
8280 call post_data(CS%id_TKE_conv_s2, CS%diag_TKE_conv_s2, CS%diag)
8291 if (CS%id_PE_detrain > 0) &
8300 call post_data(CS%id_PE_detrain, CS%diag_PE_detrain, CS%diag)
8311 if (CS%id_PE_detrain2 > 0) &
8320 call post_data(CS%id_PE_detrain2, CS%diag_PE_detrain2, CS%diag)
8331 if (CS%id_h_mismatch > 0) &
8340 call post_data(CS%id_h_mismatch, h_miss, CS%diag)
8351 if (CS%id_Hsfc_used > 0) &
8360 call post_data(CS%id_Hsfc_used, Hsfc_used, CS%diag)
8371 if (CS%id_Hsfc_max > 0) &
8380 call post_data(CS%id_Hsfc_max, Hsfc_max, CS%diag)
8391 if (CS%id_Hsfc_min > 0) &
8400 call post_data(CS%id_Hsfc_min, Hsfc_min, CS%diag)
841 endif
842
843end subroutine bulkmixedlayer
844
845!> This subroutine does instantaneous convective entrainment into the buffer
846!! layers and mixed layers to remove hydrostatic instabilities. Any water that
847!! is lighter than currently in the mixed- or buffer- layer is entrained.
848180subroutine convective_adjustment(h, u, v, R0, SpV0, Rcv, T, S, eps, d_eb, &
849180 dKE_CA, cTKE, j, G, GV, US, CS, nz_conv)
850 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
851 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
852 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2].
853 !! The units of h are referred to as H below.
854 real, dimension(SZI_(G),SZK_(GV)), intent(inout) :: u !< Zonal velocities interpolated to h
855 !! points [L T-1 ~> m s-1].
856 real, dimension(SZI_(G),SZK_(GV)), intent(inout) :: v !< Zonal velocities interpolated to h
857 !! points [L T-1 ~> m s-1].
858 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: R0 !< Potential density referenced to
859 !! surface pressure [R ~> kg m-3].
860 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: SpV0 !< Specific volume referenced to
861 !! surface pressure [R-1 ~> m3 kg-1].
862 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: Rcv !< The coordinate defining potential
863 !! density [R ~> kg m-3].
864 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Layer temperatures [C ~> degC].
865 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Layer salinities [S ~> ppt].
866 real, dimension(SZI_(G),SZK_(GV)), intent(in) :: eps !< The negligibly small amount of water
867 !! that will be left in each layer [H ~> m or kg m-2].
868 real, dimension(SZI_(G),SZK_(GV)), intent(inout) :: d_eb !< The downward increase across a layer
869 !! in the entrainment from below [H ~> m or kg m-2].
870 !! Positive values go with mass gain by
871 !! a layer.
872 real, dimension(SZI_(G),SZK_(GV)), intent(out) :: dKE_CA !< The vertically integrated change in
873 !! kinetic energy due to convective
874 !! adjustment [H Z2 T-2 ~> m3 s-2 or J m-2].
875 real, dimension(SZI_(G),SZK_(GV)), intent(out) :: cTKE !< The buoyant turbulent kinetic energy
876 !! source due to convective adjustment
877 !! [H Z2 T-2 ~> m3 s-2 or J m-2].
878 integer, intent(in) :: j !< The j-index to work on.
879 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
880 type(bulkmixedlayer_CS), intent(in) :: CS !< Bulk mixed layer control structure
881 integer, optional, intent(in) :: nz_conv !< If present, the number of layers
882 !! over which to do convective adjustment
883 !! (perhaps CS%nkml).
884
885 ! Local variables
886 real, dimension(SZI_(G)) :: &
887360 R0_tot, & ! The integrated potential density referenced to the surface
888 ! of the layers which are fully entrained [H R ~> kg m-2 or kg2 m-5].
889360 SpV0_tot, & ! The integrated specific volume referenced to the surface
890 ! of the layers which are fully entrained [H R-1 ~> m4 kg-1 or m].
891360 Rcv_tot, & ! The integrated coordinate value potential density of the
892 ! layers that are fully entrained [H R ~> kg m-2 or kg2 m-5].
893360 Ttot, & ! The integrated temperature of layers which are fully
894 ! entrained [C H ~> degC m or degC kg m-2].
895360 Stot, & ! The integrated salt of layers which are fully entrained
896 ! [H S ~> m ppt or ppt kg m-2].
897360 uhtot, & ! The depth integrated zonal velocities in the mixed layer [H L T-1 ~> m2 s-1 or kg m-1 s-1]
898360 vhtot, & ! The depth integrated meridional velocities in the mixed layer [H L T-1 ~> m2 s-1 or kg m-1 s-1]
899360 KE_orig, & ! The total mean kinetic energy per unit area in the mixed layer before
900 ! convection, [H L2 T-2 ~> m3 s-2 or kg s-2].
901360 h_orig_k1 ! The depth of layer k1 before convective adjustment [H ~> m or kg m-2].
902 real :: h_ent ! The thickness from a layer that is entrained [H ~> m or kg m-2].
903 real :: Ih ! The inverse of a thickness [H-1 ~> m-1 or m2 kg-1].
904 real :: g_H_2Rho0 ! Half the gravitational acceleration times
905 ! the conversion from H to Z divided by the mean density,
906 ! in [Z2 T-2 H-1 R-1 ~> m4 s-2 kg-1 or m7 s-2 kg-2].
907 logical :: unstable
908 integer :: is, ie, nz, i, k, k1, nzc, nkmb
909
910180 is = G%isc ; ie = G%iec ; nz = GV%ke
911180 g_H_2Rho0 = (GV%g_Earth_Z_T2 * GV%H_to_Z) / (2.0 * GV%Rho0)
912180 nzc = nz ; if (present(nz_conv)) nzc = nz_conv
913180 nkmb = CS%nkml+CS%nkbl
914
915! Undergo instantaneous entrainment into the buffer layers and mixed layers
916! to remove hydrostatic instabilities. Any water that is lighter than currently
917! in the layer is entrained.
918900 do k1=min(nzc-1,nkmb),1,-1
919259920 do i=is,ie
920259200 h_orig_k1(i) = h(i,k1)
921259200 KE_orig(i) = 0.5*h(i,k1)*((u(i,k1)**2) + (v(i,k1)**2))
922259200 uhtot(i) = h(i,k1)*u(i,k1) ; vhtot(i) = h(i,k1)*v(i,k1)
923259200 if (CS%nonBous_energetics) then
9240 SpV0_tot(i) = SpV0(i,k1) * h(i,k1)
925 else
926259200 R0_tot(i) = R0(i,k1) * h(i,k1)
927 endif
928259200 cTKE(i,k1) = 0.0 ; dKE_CA(i,k1) = 0.0
929
930259200 Rcv_tot(i) = Rcv(i,k1) * h(i,k1)
931259920 Ttot(i) = T(i,k1) * h(i,k1) ; Stot(i) = S(i,k1) * h(i,k1)
932 enddo
93314760 do k=k1+1,nzc
9345069160 do i=is,ie
9355054400 if (CS%nonBous_energetics) then
9360 unstable = (SpV0_tot(i) < h(i,k1)*SpV0(i,k))
937 else
9385054400 unstable = (R0_tot(i) > h(i,k1)*R0(i,k))
939 endif
9405068440 if ((h(i,k) > eps(i,k)) .and. unstable) then
941134699 h_ent = h(i,k)-eps(i,k)
942134699 if (CS%nonBous_energetics) then
943 ! This and the other energy calculations assume that specific volume is
944 ! conserved during mixing, which ignores certain thermobaric contributions.
945 cTKE(i,k1) = cTKE(i,k1) + 0.5 * h_ent * (GV%g_Earth_Z_T2 * GV%H_to_RZ) * &
9460 (h(i,k1)*SpV0(i,k) - SpV0_tot(i)) * CS%nstar2
9470 SpV0_tot(i) = SpV0_tot(i) + h_ent * SpV0(i,k)
948 else
949 cTKE(i,k1) = cTKE(i,k1) + h_ent * g_H_2Rho0 * &
950134699 (R0_tot(i) - h(i,k1)*R0(i,k)) * CS%nstar2
951134699 R0_tot(i) = R0_tot(i) + h_ent * R0(i,k)
952 endif
953134699 if (k < nkmb) then
95410556 cTKE(i,k1) = cTKE(i,k1) + cTKE(i,k)
95510556 dKE_CA(i,k1) = dKE_CA(i,k1) + dKE_CA(i,k)
956 endif
957 KE_orig(i) = KE_orig(i) + 0.5*h_ent* &
958134699 ((u(i,k)*u(i,k)) + (v(i,k)*v(i,k)))
959134699 uhtot(i) = uhtot(i) + h_ent*u(i,k)
960134699 vhtot(i) = vhtot(i) + h_ent*v(i,k)
961
962134699 Rcv_tot(i) = Rcv_tot(i) + h_ent * Rcv(i,k)
963134699 Ttot(i) = Ttot(i) + h_ent * T(i,k)
964134699 Stot(i) = Stot(i) + h_ent * S(i,k)
965134699 h(i,k1) = h(i,k1) + h_ent ; h(i,k) = eps(i,k)
966
967134699 d_eb(i,k) = d_eb(i,k) - h_ent
968134699 d_eb(i,k1) = d_eb(i,k1) + h_ent
969 endif
970 enddo
971 enddo
972! Determine the temperature, salinity, and velocities of the mixed or buffer
973! layer in question, if it has entrained.
974260100 do i=is,ie ; if (h(i,k1) > h_orig_k1(i)) then
97528168 Ih = 1.0 / h(i,k1)
97628168 if (CS%nonBous_energetics) then
9770 SpV0(i,k1) = SpV0_tot(i) * Ih
978 else
97928168 R0(i,k1) = R0_tot(i) * Ih
980 endif
98128168 u(i,k1) = uhtot(i) * Ih ; v(i,k1) = vhtot(i) * Ih
982 dKE_CA(i,k1) = dKE_CA(i,k1) + CS%bulk_Ri_convective * &
98328168 (KE_orig(i) - 0.5*h(i,k1)*((u(i,k1)**2) + (v(i,k1)**2)))
98428168 Rcv(i,k1) = Rcv_tot(i) * Ih
98528168 T(i,k1) = Ttot(i) * Ih ; S(i,k1) = Stot(i) * Ih
986 endif ; enddo
987 enddo
988! If lower mixed or buffer layers are massless, give them the properties of the
989! layer above.
990195120 do k=2,min(nzc,nkmb) ; do i=is,ie ; if (h(i,k) == 0.0) then
99116142 if (CS%nonBous_energetics) then
9920 SpV0(i,k) = SpV0(i,k-1)
993 else
99416142 R0(i,k) = R0(i,k-1)
995 endif
99616142 Rcv(i,k) = Rcv(i,k-1) ; T(i,k) = T(i,k-1) ; S(i,k) = S(i,k-1)
997 endif ; enddo ; enddo
998
999180end subroutine convective_adjustment
1000
1001!> This subroutine causes the mixed layer to entrain to the depth of free
1002!! convection. The depth of free convection is the shallowest depth at which the
1003!! fluid is denser than the average of the fluid above.
1004180subroutine mixedlayer_convection(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, &
1005180 R0_tot, SpV0_tot, Rcv_tot, u, v, T, S, R0, SpV0, Rcv, eps, &
1006180 dR0_dT, dSpV0_dT, dRcv_dT, dR0_dS, dSpV0_dS, dRcv_dS, &
1007180 netMassInOut, netMassOut, Net_heat, Net_salt, &
1008180 nsw, Pen_SW_bnd, opacity_band, Conv_En, &
1009180 dKE_FC, j, ksort, G, GV, US, CS, tv, fluxes, dt, &
1010 aggregate_FW_forcing)
1011 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
1012 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
1013 real, dimension(SZI_(G),SZK0_(GV)), &
1014 intent(inout) :: h !< Layer thickness [H ~> m or kg m-2].
1015 !! The units of h are referred to as H below.
1016 real, dimension(SZI_(G),SZK_(GV)), &
1017 intent(inout) :: d_eb !< The downward increase across a layer in the
1018 !! layer in the entrainment from below [H ~> m or kg m-2].
1019 !! Positive values go with mass gain by a layer.
1020 real, dimension(SZI_(G)), intent(out) :: htot !< The accumulated mixed layer thickness [H ~> m or kg m-2].
1021 real, dimension(SZI_(G)), intent(out) :: Ttot !< The depth integrated mixed layer temperature
1022 !! [C H ~> degC m or degC kg m-2].
1023 real, dimension(SZI_(G)), intent(out) :: Stot !< The depth integrated mixed layer salinity
1024 !! [S H ~> ppt m or ppt kg m-2].
1025 real, dimension(SZI_(G)), intent(out) :: uhtot !< The depth integrated mixed layer zonal
1026 !! velocity [H L T-1 ~> m2 s-1 or kg m-1 s-1].
1027 real, dimension(SZI_(G)), intent(out) :: vhtot !< The integrated mixed layer meridional
1028 !! velocity [H L T-1 ~> m2 s-1 or kg m-1 s-1].
1029 real, dimension(SZI_(G)), intent(out) :: R0_tot !< The integrated mixed layer potential density referenced
1030 !! to 0 pressure [H R ~> kg m-2 or kg2 m-5].
1031 real, dimension(SZI_(G)), intent(out) :: SpV0_tot !< The integrated mixed layer specific volume referenced
1032 !! to 0 pressure [H R-1 ~> m4 kg-1 or m].
1033 real, dimension(SZI_(G)), intent(out) :: Rcv_tot !< The integrated mixed layer coordinate
1034 !! variable potential density [H R ~> kg m-2 or kg2 m-5].
1035 real, dimension(SZI_(G),SZK_(GV)), &
1036 intent(in) :: u !< Zonal velocities interpolated to h points [L T-1 ~> m s-1].
1037 real, dimension(SZI_(G),SZK_(GV)), &
1038 intent(in) :: v !< Zonal velocities interpolated to h points [L T-1 ~> m s-1].
1039 real, dimension(SZI_(G),SZK0_(GV)), &
1040 intent(in) :: T !< Layer temperatures [C ~> degC].
1041 real, dimension(SZI_(G),SZK0_(GV)), &
1042 intent(in) :: S !< Layer salinities [S ~> ppt].
1043 real, dimension(SZI_(G),SZK0_(GV)), &
1044 intent(in) :: R0 !< Potential density referenced to
1045 !! surface pressure [R ~> kg m-3].
1046 real, dimension(SZI_(G),SZK0_(GV)), &
1047 intent(in) :: SpV0 !< Specific volume referenced to
1048 !! surface pressure [R-1 ~> m3 kg-1].
1049 real, dimension(SZI_(G),SZK0_(GV)), &
1050 intent(in) :: Rcv !< The coordinate defining potential
1051 !! density [R ~> kg m-3].
1052 real, dimension(SZI_(G),SZK_(GV)), &
1053 intent(in) :: eps !< The negligibly small amount of water
1054 !! that will be left in each layer [H ~> m or kg m-2].
1055 real, dimension(SZI_(G)), intent(in) :: dR0_dT !< The partial derivative of R0 with respect to
1056 !! temperature [R C-1 ~> kg m-3 degC-1].
1057 real, dimension(SZI_(G)), intent(in) :: dSpV0_dT !< The partial derivative of SpV0 with respect to
1058 !! temperature [R-1 C-1 ~> m3 kg-1 degC-1].
1059 real, dimension(SZI_(G)), intent(in) :: dRcv_dT !< The partial derivative of Rcv with respect to
1060 !! temperature [R C-1 ~> kg m-3 degC-1].
1061 real, dimension(SZI_(G)), intent(in) :: dR0_dS !< The partial derivative of R0 with respect to
1062 !! salinity [R S-1 ~> kg m-3 ppt-1].
1063 real, dimension(SZI_(G)), intent(in) :: dSpV0_dS !< The partial derivative of SpV0 with respect to
1064 !! salinity [R-1 S-1 ~> m3 kg-1 ppt-1].
1065 real, dimension(SZI_(G)), intent(in) :: dRcv_dS !< The partial derivative of Rcv with respect to
1066 !! salinity [R S-1 ~> kg m-3 ppt-1].
1067 real, dimension(SZI_(G)), intent(in) :: netMassInOut !< The net mass flux (if non-Boussinesq)
1068 !! or volume flux (if Boussinesq) into the ocean
1069 !! within a time step [H ~> m or kg m-2]. (I.e. P+R-E.)
1070 real, dimension(SZI_(G)), intent(in) :: netMassOut !< The mass or volume flux out of the ocean
1071 !! within a time step [H ~> m or kg m-2].
1072 real, dimension(SZI_(G)), intent(in) :: Net_heat !< The net heating at the surface over a time
1073 !! step [C H ~> degC m or degC kg m-2]. Any penetrating
1074 !! shortwave radiation is not included in Net_heat.
1075 real, dimension(SZI_(G)), intent(in) :: Net_salt !< The net surface salt flux into the ocean
1076 !! over a time step [S H ~> ppt m or ppt kg m-2].
1077 integer, intent(in) :: nsw !< The number of bands of penetrating
1078 !! shortwave radiation.
1079 real, dimension(max(nsw,1),SZI_(G)), intent(inout) :: Pen_SW_bnd !< The penetrating shortwave
1080 !! heating at the sea surface in each penetrating
1081 !! band [C H ~> degC m or degC kg m-2].
1082 real, dimension(max(nsw,1),SZI_(G),SZK_(GV)), intent(in) :: opacity_band !< The opacity in each band of
1083 !! penetrating shortwave radiation [H-1 ~> m-1 or m2 kg-1].
1084 real, dimension(SZI_(G)), intent(out) :: Conv_En !< The buoyant turbulent kinetic energy source
1085 !! due to free convection [H Z2 T-2 ~> m3 s-2 or J m-2].
1086 real, dimension(SZI_(G)), intent(out) :: dKE_FC !< The vertically integrated change in kinetic
1087 !! energy due to free convection [H Z2 T-2 ~> m3 s-2 or J m-2].
1088 integer, intent(in) :: j !< The j-index to work on.
1089 integer, dimension(SZI_(G),SZK_(GV)), &
1090 intent(in) :: ksort !< The density-sorted k-indices.
1091 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
1092 type(bulkmixedlayer_CS), intent(in) :: CS !< Bulk mixed layer control structure
1093 type(thermo_var_ptrs), intent(inout) :: tv !< A structure containing pointers to any
1094 !! available thermodynamic fields. Absent
1095 !! fields have NULL pointers.
1096 type(forcing), intent(inout) :: fluxes !< A structure containing pointers to any
1097 !! possible forcing fields. Unused fields
1098 !! have NULL pointers.
1099 real, intent(in) :: dt !< Time increment [T ~> s].
1100 logical, intent(in) :: aggregate_FW_forcing !< If true, the net incoming and
1101 !! outgoing surface freshwater fluxes are
1102 !! combined before being applied, instead of
1103 !! being applied separately.
1104
1105! This subroutine causes the mixed layer to entrain to the depth of free
1106! convection. The depth of free convection is the shallowest depth at which the
1107! fluid is denser than the average of the fluid above.
1108
1109 ! Local variables
1110 real, dimension(SZI_(G)) :: &
1111360 massOutRem, & ! Evaporation that remains to be supplied [H ~> m or kg m-2].
1112360 netMassIn ! mass entering through ocean surface [H ~> m or kg m-2]
1113 real :: SW_trans ! The fraction of shortwave radiation
1114 ! that is not absorbed in a layer [nondim].
1115 real :: Pen_absorbed ! The amount of penetrative shortwave radiation
1116 ! that is absorbed in a layer [C H ~> degC m or degC kg m-2].
1117 real :: h_avail ! The thickness in a layer available for
1118 ! entrainment [H ~> m or kg m-2].
1119 real :: h_ent ! The thickness from a layer that is entrained [H ~> m or kg m-2].
1120 real :: T_precip ! The temperature of the precipitation [C ~> degC].
1121 real :: C1_3, C1_6 ! 1/3 and 1/6 [nondim]
1122 real :: En_fn, Frac, x1 ! Nondimensional temporary variables [nondim].
1123 real :: dr, dr0 ! Temporary variables [R H ~> kg m-2 or kg2 m-5] or [H R-1 ~> m4 kg-1 or m].
1124 real :: dr_ent, dr_comp ! Temporary variables [R H ~> kg m-2 or kg2 m-5].
1125 real :: dr_dh ! The partial derivative of dr_ent with h_ent [R ~> kg m-3].
1126 real :: h_min, h_max ! The minimum and maximum estimates for h_ent [H ~> m or kg m-2]
1127 real :: h_prev ! The previous estimate for h_ent [H ~> m or kg m-2]
1128 real :: h_evap ! The thickness that is evaporated [H ~> m or kg m-2].
1129 real :: dh_Newt ! The Newton's method estimate of the change in
1130 ! h_ent between iterations [H ~> m or kg m-2].
1131 real :: g_H_2Rho0 ! Half the gravitational acceleration times
1132 ! the conversion from H to Z divided by the mean density,
1133 ! [Z2 T-2 H-1 R-1 ~> m4 s-2 kg-1 or m7 s-2 kg-2].
1134 real :: Angstrom ! The minimum layer thickness [H ~> m or kg m-2].
1135 real :: opacity ! The opacity converted to inverse thickness units [H-1 ~> m-1 or m2 kg-1]
1136 real :: sum_Pen_En ! The potential energy change due to penetrating
1137 ! shortwave radiation, integrated over a layer
1138 ! [H R ~> kg m-2 or kg2 m-5].
1139 real :: Idt ! 1.0/dt [T-1 ~> s-1]
1140 integer :: is, ie, nz, i, k, ks, itt, n
1141 real, dimension(max(nsw,1)) :: &
1142360 C2, & ! Temporary variable [R H-1 ~> kg m-4 or m-1].
1143360 r_SW_top ! Temporary variables [H R ~> kg m-2 or kg2 m-5].
1144
1145180 Angstrom = GV%Angstrom_H
1146180 C1_3 = 1.0/3.0 ; C1_6 = 1.0/6.0
1147180 g_H_2Rho0 = (GV%g_Earth_Z_T2 * GV%H_to_Z) / (2.0 * GV%Rho0)
1148180 Idt = 1.0 / dt
1149180 is = G%isc ; ie = G%iec ; nz = GV%ke
1150
115164980 do i=is,ie ; if (ksort(i,1) > 0) then
115264800 k = ksort(i,1)
1153
115464800 if (aggregate_FW_forcing) then
115564800 massOutRem(i) = 0.0
115664800 if (netMassInOut(i) < 0.0) massOutRem(i) = -netMassInOut(i)
115764800 netMassIn(i) = netMassInOut(i) + massOutRem(i)
1158 else
11590 massOutRem(i) = -netMassOut(i)
11600 netMassIn(i) = netMassInOut(i) - netMassOut(i)
1161 endif
1162
1163 ! htot is an Angstrom (taken from layer 1) plus any net precipitation.
116464800 h_ent = max(min(Angstrom,h(i,k)-eps(i,k)),0.0)
116564800 htot(i) = h_ent + netMassIn(i)
116664800 h(i,k) = h(i,k) - h_ent
116764800 d_eb(i,k) = d_eb(i,k) - h_ent
1168
116964800 Pen_absorbed = 0.0
1170129600 do n=1,nsw ; if (Pen_SW_bnd(n,i) > 0.0) then
11710 SW_trans = exp(-htot(i)*opacity_band(n,i,k))
11720 Pen_absorbed = Pen_absorbed + Pen_SW_bnd(n,i) * (1.0-SW_trans)
11730 Pen_SW_bnd(n,i) = Pen_SW_bnd(n,i) * SW_trans
1174 endif ; enddo
1175
1176 ! Precipitation is assumed to have the same temperature and velocity
1177 ! as layer 1. Because layer 1 might not be the topmost layer, this
1178 ! involves multiple terms.
117964800 T_precip = T(i,1)
1180 Ttot(i) = (Net_heat(i) + (netMassIn(i) * T_precip + h_ent * T(i,k))) + &
118164800 Pen_absorbed
1182 ! Net_heat contains both heat fluxes and the heat content of mass fluxes.
1183 !! Ttot(i) = netMassIn(i) * T_precip + h_ent * T(i,k)
1184 !! Ttot(i) = Net_heat(i) + Ttot(i)
1185 !! Ttot(i) = Ttot(i) + Pen_absorbed
1186 ! smg:
1187 ! Ttot(i) = (Net_heat(i) + (h_ent * T(i,k))) + Pen_absorbed
118864800 Stot(i) = h_ent*S(i,k) + Net_salt(i)
118964800 uhtot(i) = u(i,1)*netMassIn(i) + u(i,k)*h_ent
119064800 vhtot(i) = v(i,1)*netMassIn(i) + v(i,k)*h_ent
119164800 if (CS%nonBous_energetics) then
1192 SpV0_tot(i) = (h_ent*SpV0(i,k) + netMassIn(i)*SpV0(i,1)) + &
1193! dSpV0_dT(i)*netMassIn(i)*(T_precip - T(i,1)) + &
1194 (dSpV0_dT(i)*(Net_heat(i) + Pen_absorbed) - &
11950 dSpV0_dS(i) * (netMassIn(i) * S(i,1) - Net_salt(i)))
1196 else
1197 R0_tot(i) = (h_ent*R0(i,k) + netMassIn(i)*R0(i,1)) + &
1198! dR0_dT(i)*netMassIn(i)*(T_precip - T(i,1)) + &
1199 (dR0_dT(i)*(Net_heat(i) + Pen_absorbed) - &
120064800 dR0_dS(i) * (netMassIn(i) * S(i,1) - Net_salt(i)))
1201 endif
1202 Rcv_tot(i) = (h_ent*Rcv(i,k) + netMassIn(i)*Rcv(i,1)) + &
1203! dRcv_dT(i)*netMassIn(i)*(T_precip - T(i,1)) + &
1204 (dRcv_dT(i)*(Net_heat(i) + Pen_absorbed) - &
120564800 dRcv_dS(i) * (netMassIn(i) * S(i,1) - Net_salt(i)))
120664800 Conv_En(i) = 0.0 ; dKE_FC(i) = 0.0
120764800 if (associated(fluxes%heat_content_massin)) &
1208 fluxes%heat_content_massin(i,j) = fluxes%heat_content_massin(i,j) + &
120964800 T_precip * netMassIn(i) * GV%H_to_RZ * tv%C_p * Idt
121064800 if (associated(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + &
121164800 T_precip * netMassIn(i) * GV%H_to_RZ
1212 else ! This is a massless column, but zero out the summed variables anyway for safety.
12130 htot(i) = 0.0 ; Ttot(i) = 0.0 ; Stot(i) = 0.0 ; Rcv_tot = 0.0
12140 R0_tot(i) = 0.0 ; SpV0_tot(i) = 0.0
12150 uhtot(i) = 0.0 ; vhtot(i) = 0.0 ; Conv_En(i) = 0.0 ; dKE_FC(i) = 0.0
1216 endif ; enddo
1217
1218 ! Now do netMassOut case in this block.
1219 ! At this point htot contains an Angstrom of fluid from layer 0 plus netMassIn.
12204140 do ks=1,nz
12211429740 do i=is,ie ; if (ksort(i,ks) > 0) then
12221425600 k = ksort(i,ks)
1223
12241425600 if ((htot(i) < Angstrom) .and. (h(i,k) > eps(i,k))) then
1225 ! If less than an Angstrom was available from the layers above plus
1226 ! any precipitation, add more fluid from this layer.
12270 h_ent = min(Angstrom-htot(i), h(i,k)-eps(i,k))
12280 htot(i) = htot(i) + h_ent
12290 h(i,k) = h(i,k) - h_ent
12300 d_eb(i,k) = d_eb(i,k) - h_ent
1231
12320 if (CS%nonBous_energetics) then
12330 SpV0_tot(i) = SpV0_tot(i) + h_ent*SpV0(i,k)
1234 else
12350 R0_tot(i) = R0_tot(i) + h_ent*R0(i,k)
1236 endif
12370 uhtot(i) = uhtot(i) + h_ent*u(i,k)
12380 vhtot(i) = vhtot(i) + h_ent*v(i,k)
1239
12400 Rcv_tot(i) = Rcv_tot(i) + h_ent*Rcv(i,k)
12410 Ttot(i) = Ttot(i) + h_ent*T(i,k)
12420 Stot(i) = Stot(i) + h_ent*S(i,k)
1243 endif
1244
1245 ! Water is removed from the topmost layers with any mass.
1246 ! We may lose layers if they are thin enough.
1247 ! The salt that is left behind goes into Stot.
12481425600 if ((massOutRem(i) > 0.0) .and. (h(i,k) > eps(i,k))) then
12490 if (massOutRem(i) > (h(i,k) - eps(i,k))) then
12500 h_evap = h(i,k) - eps(i,k)
12510 h(i,k) = eps(i,k)
12520 massOutRem(i) = massOutRem(i) - h_evap
1253 else
12540 h_evap = massOutRem(i)
12550 h(i,k) = h(i,k) - h_evap
12560 massOutRem(i) = 0.0
1257 endif
1258
12590 Stot(i) = Stot(i) + h_evap*S(i,k)
12600 if (CS%nonBous_energetics) then
12610 SpV0_tot(i) = SpV0_tot(i) + dSpV0_dS(i)*h_evap*S(i,k)
1262 else
12630 R0_tot(i) = R0_tot(i) + dR0_dS(i)*h_evap*S(i,k)
1264 endif
12650 Rcv_tot(i) = Rcv_tot(i) + dRcv_dS(i)*h_evap*S(i,k)
12660 d_eb(i,k) = d_eb(i,k) - h_evap
1267
1268 ! smg: when resolve the A=B code, we will set
1269 ! heat_content_massout = heat_content_massout - T(i,k)*h_evap*GV%H_to_RZ*tv%C_p*Idt
1270 ! by uncommenting the lines here.
1271 ! we will also then completely remove TempXpme from the model.
12720 if (associated(fluxes%heat_content_massout)) &
1273 fluxes%heat_content_massout(i,j) = fluxes%heat_content_massout(i,j) - &
12740 T(i,k)*h_evap*GV%H_to_RZ * tv%C_p * Idt
12750 if (associated(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) - &
12760 T(i,k)*h_evap*GV%H_to_RZ
1277
1278 endif
1279
1280 ! The following section calculates how much fluid will be entrained.
12811425600 h_avail = h(i,k) - eps(i,k)
12821425600 if (h_avail > 0.0) then
1283592688 h_ent = 0.0
1284
1285592688 if (CS%nonBous_energetics) then
12860 dr = htot(i)*SpV0(i,k) - SpV0_tot(i)
1287
12880 dr0 = dr
12890 do n=1,nsw ; if (Pen_SW_bnd(n,i) > 0.0) then
1290 dr0 = dr0 + (dSpV0_dT(i)*Pen_SW_bnd(n,i)) * &
12910 opacity_band(n,i,k)*htot(i)
1292 endif ; enddo
1293 else
1294592688 dr = R0_tot(i) - htot(i)*R0(i,k)
1295
1296592688 dr0 = dr
12971185376 do n=1,nsw ; if (Pen_SW_bnd(n,i) > 0.0) then
1298 dr0 = dr0 - (dR0_dT(i)*Pen_SW_bnd(n,i)) * &
12990 opacity_band(n,i,k)*htot(i)
1300 endif ; enddo
1301 endif
1302
1303 ! Some entrainment will occur from this layer.
1304592688 if (dr0 > 0.0) then
13054881 dr_comp = dr
13069762 do n=1,nsw ; if (Pen_SW_bnd(n,i) > 0.0) then
1307 ! Compare the density at the bottom of a layer with the
1308 ! density averaged over the mixed layer and that layer.
13090 opacity = opacity_band(n,i,k)
13100 SW_trans = exp(-h_avail*opacity)
13110 if (CS%nonBous_energetics) then
1312 dr_comp = dr_comp - (dSpV0_dT(i)*Pen_SW_bnd(n,i)) * &
13130 ((1.0 - SW_trans) - opacity*(htot(i)+h_avail)*SW_trans)
1314 else
1315 dr_comp = dr_comp + (dR0_dT(i)*Pen_SW_bnd(n,i)) * &
13160 ((1.0 - SW_trans) - opacity*(htot(i)+h_avail)*SW_trans)
1317 endif
1318 endif ; enddo
13194881 if (dr_comp >= 0.0) then
1320 ! The entire layer is entrained.
13214881 h_ent = h_avail
1322 else
1323 ! The layer is partially entrained. Iterate to determine how much
1324 ! entrainment occurs. Solve for the h_ent at which dr_ent = 0.
1325
1326 ! Instead of assuming that the curve is linear between the two end
1327 ! points, assume that the change is concentrated near small values
1328 ! of entrainment. On average, this saves about 1 iteration.
13290 Frac = dr0 / (dr0 - dr_comp)
13300 h_ent = h_avail * Frac*Frac
13310 h_min = 0.0 ; h_max = h_avail
1332
13330 do n=1,nsw
13340 if (CS%nonBous_energetics) then
13350 r_SW_top(n) = -dSpV0_dT(i) * Pen_SW_bnd(n,i)
1336 else
13370 r_SW_top(n) = dR0_dT(i) * Pen_SW_bnd(n,i)
1338 endif
13390 C2(n) = r_SW_top(n) * opacity_band(n,i,k)**2
1340 enddo
13410 do itt=1,10
13420 dr_ent = dr ; dr_dh = 0.0
13430 do n=1,nsw
13440 opacity = opacity_band(n,i,k)
13450 SW_trans = exp(-h_ent*opacity)
1346 dr_ent = dr_ent + r_SW_top(n) * ((1.0 - SW_trans) - &
13470 opacity*(htot(i)+h_ent)*SW_trans)
13480 dr_dh = dr_dh + C2(n) * (htot(i)+h_ent) * SW_trans
1349 enddo
1350
13510 if (dr_ent > 0.0) then
13520 h_min = h_ent
1353 else
13540 h_max = h_ent
1355 endif
1356
13570 dh_Newt = -dr_ent / dr_dh
13580 h_prev = h_ent ; h_ent = h_prev+dh_Newt
13590 if (h_ent > h_max) then
13600 h_ent = 0.5*(h_prev+h_max)
13610 elseif (h_ent < h_min) then
13620 h_ent = 0.5*(h_prev+h_min)
1363 endif
1364
13650 if (ABS(dh_Newt) < 0.2*Angstrom) exit
1366 enddo
1367
1368 endif
1369
1370 ! Now that the amount of entrainment (h_ent) has been determined,
1371 ! calculate changes in various terms.
13724881 sum_Pen_En = 0.0 ; Pen_absorbed = 0.0
13739762 do n=1,nsw ; if (Pen_SW_bnd(n,i) > 0.0) then
13740 opacity = opacity_band(n,i,k)
13750 SW_trans = exp(-h_ent*opacity)
1376
13770 x1 = h_ent*opacity
13780 if (x1 < 2.0e-5) then
1379 En_fn = (opacity*htot(i)*(1.0 - 0.5*(x1 - C1_3*x1)) + &
13800 x1*x1*C1_6)
1381 else
1382 En_fn = ((opacity*htot(i) + 2.0) * &
13830 ((1.0-SW_trans) / x1) - 1.0 + SW_trans)
1384 endif
13850 if (CS%nonBous_energetics) then
13860 sum_Pen_En = sum_Pen_En + (dSpV0_dT(i)*Pen_SW_bnd(n,i)) * En_fn
1387 else
13880 sum_Pen_En = sum_Pen_En - (dR0_dT(i)*Pen_SW_bnd(n,i)) * En_fn
1389 endif
1390
13910 Pen_absorbed = Pen_absorbed + Pen_SW_bnd(n,i) * (1.0 - SW_trans)
13920 Pen_SW_bnd(n,i) = Pen_SW_bnd(n,i) * SW_trans
1393 endif ; enddo
1394
13954881 if (CS%nonBous_energetics) then
1396 ! This and the other energy calculations assume that specific volume is
1397 ! conserved during mixing, which ignores certain thermobaric contributions.
1398 Conv_En(i) = Conv_En(i) + 0.5 * (GV%g_Earth_Z_T2 * GV%H_to_RZ) * h_ent * &
13990 ( (SpV0(i,k)*htot(i) - SpV0_tot(i)) + sum_Pen_En )
14000 SpV0_tot(i) = SpV0_tot(i) + (h_ent * SpV0(i,k) + Pen_absorbed*dSpV0_dT(i))
1401 else
1402 Conv_En(i) = Conv_En(i) + g_H_2Rho0 * h_ent * &
14034881 ( (R0_tot(i) - R0(i,k)*htot(i)) + sum_Pen_En )
14044881 R0_tot(i) = R0_tot(i) + (h_ent * R0(i,k) + Pen_absorbed*dR0_dT(i))
1405 endif
1406
14074881 Stot(i) = Stot(i) + h_ent * S(i,k)
14084881 Ttot(i) = Ttot(i) + (h_ent * T(i,k) + Pen_absorbed)
14094881 Rcv_tot(i) = Rcv_tot(i) + (h_ent * Rcv(i,k) + Pen_absorbed*dRcv_dT(i))
1410 endif ! dr0 > 0.0
1411
1412
1413592688 if ((h_ent > 0.0) .and. (htot(i) > 0.0)) &
1414 dKE_FC(i) = dKE_FC(i) + CS%bulk_Ri_convective * 0.5 * &
1415 ((h_ent) / (htot(i)*(h_ent+htot(i)))) * &
14164881 (((uhtot(i)-u(i,k)*htot(i))**2) + ((vhtot(i)-v(i,k)*htot(i))**2))
1417
1418592688 if (h_ent > 0.0) then
14194881 htot(i) = htot(i) + h_ent
14204881 h(i,k) = h(i,k) - h_ent
14214881 d_eb(i,k) = d_eb(i,k) - h_ent
14224881 if (CS%convect_mom_bug) then
14230 uhtot(i) = u(i,k)*h_ent ; vhtot(i) = v(i,k)*h_ent
1424 else
14254881 uhtot(i) = uhtot(i) + h_ent*u(i,k) ; vhtot(i) = vhtot(i) + h_ent*v(i,k)
1426 endif
1427 endif
1428
1429 endif ! h_avail>0
1430 endif ; enddo ! i loop
1431 enddo ! k loop
1432
1433180end subroutine mixedlayer_convection
1434
1435!> This subroutine determines the TKE available at the depth of free
1436!! convection to drive mechanical entrainment.
1437180subroutine find_starting_TKE(htot, h_CA, fluxes, U_star_2d, Conv_En, cTKE, dKE_FC, dKE_CA, &
1438180 TKE, TKE_river, Idecay_len_TKE, cMKE, tv, dt, Idt_diag, &
1439 j, ksort, G, GV, US, CS)
1440 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
1441 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
1442 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
1443 real, dimension(SZI_(G)), intent(in) :: htot !< The accumulated mixed layer thickness
1444 !! [H ~> m or kg m-2]
1445 real, dimension(SZI_(G)), intent(in) :: h_CA !< The mixed layer depth after convective
1446 !! adjustment [H ~> m or kg m-2].
1447 type(forcing), intent(in) :: fluxes !< A structure containing pointers to any
1448 !! possible forcing fields. Unused fields
1449 !! have NULL pointers.
1450 real, dimension(SZI_(G),SZJ_(G)), intent(in) :: U_star_2d !< The wind friction velocity, calculated
1451 !! using the Boussinesq reference density or
1452 !! the time-evolving surface density in
1453 !! non-Boussinesq mode [Z T-1 ~> m s-1]
1454 real, dimension(SZI_(G)), intent(inout) :: Conv_En !< The buoyant turbulent kinetic energy source
1455 !! due to free convection [H Z2 T-2 ~> m3 s-2 or J m-2].
1456 real, dimension(SZI_(G)), intent(in) :: dKE_FC !< The vertically integrated change in
1457 !! kinetic energy due to free convection
1458 !! [H Z2 T-2 ~> m3 s-2 or J m-2].
1459 real, dimension(SZI_(G),SZK_(GV)), &
1460 intent(in) :: cTKE !< The buoyant turbulent kinetic energy
1461 !! source due to convective adjustment
1462 !! [H Z2 T-2 ~> m3 s-2 or J m-2].
1463 real, dimension(SZI_(G),SZK_(GV)), &
1464 intent(in) :: dKE_CA !< The vertically integrated change in
1465 !! kinetic energy due to convective
1466 !! adjustment [H Z2 T-2 ~> m3 s-2 or J m-2].
1467 real, dimension(SZI_(G)), intent(out) :: TKE !< The turbulent kinetic energy available for
1468 !! mixing over a time step [H Z2 T-2 ~> m3 s-2 or J m-2]
1469 real, dimension(SZI_(G)), intent(out) :: Idecay_len_TKE !< The inverse of the vertical decay
1470 !! scale for TKE [H-1 ~> m-1 or m2 kg-1].
1471 real, dimension(SZI_(G)), intent(in) :: TKE_river !< The source of turbulent kinetic energy
1472 !! available for driving mixing at river mouths
1473 !! [H Z2 T-3 ~> m3 s-3 or W m-2].
1474 real, dimension(2,SZI_(G)), intent(out) :: cMKE !< Coefficients of HpE and HpE^2 in
1475 !! calculating the denominator of MKE_rate,
1476 !! [H-1 ~> m-1 or m2 kg-1] and [H-2 ~> m-2 or m4 kg-2].
1477 type(thermo_var_ptrs), intent(inout) :: tv !< A structure containing pointers to any
1478 !! available thermodynamic fields.
1479 real, intent(in) :: dt !< The time step [T ~> s].
1480 real, intent(in) :: Idt_diag !< The inverse of the accumulated diagnostic
1481 !! time interval [T-1 ~> s-1].
1482 integer, intent(in) :: j !< The j-index to work on.
1483 integer, dimension(SZI_(G),SZK_(GV)), &
1484 intent(in) :: ksort !< The density-sorted k-indices.
1485 type(bulkmixedlayer_CS), intent(inout) :: CS !< Bulk mixed layer control structure
1486
1487! This subroutine determines the TKE available at the depth of free
1488! convection to drive mechanical entrainment.
1489
1490 ! Local variables
1491 real :: dKE_conv ! The change in mean kinetic energy due to all convection [H Z2 T-2 ~> m3 s-2 or J m-2].
1492 real :: nstar_FC ! The effective efficiency with which the energy released by
1493 ! free convection is converted to TKE, often ~0.2 [nondim].
1494 real :: nstar_CA ! The effective efficiency with which the energy released by
1495 ! convective adjustment is converted to TKE, often ~0.2 [nondim].
1496 real :: TKE_CA ! The potential energy released by convective adjustment if
1497 ! that release is positive [H Z2 T-2 ~> m3 s-2 or J m-2].
1498 real :: MKE_rate_CA ! MKE_rate for convective adjustment [nondim], 0 to 1.
1499 real :: MKE_rate_FC ! MKE_rate for free convection [nondim], 0 to 1.
1500 real :: totEn_Z ! The total potential energy released by convection, [H Z2 T-2 ~> m3 s-2 or J m-2].
1501 real :: Ih ! The inverse of a thickness [H-1 ~> m-1 or m2 kg-1].
1502 real :: exp_kh ! The nondimensional decay of TKE across a layer [nondim].
1503 real :: absf ! The absolute value of f averaged to thickness points [T-1 ~> s-1].
1504 real :: U_star ! The friction velocity [Z T-1 ~> m s-1].
1505 real :: absf_Ustar ! The absolute value of f divided by U_star converted to thickness units [H-1 ~> m-1 or m2 kg-1]
1506 real :: wind_TKE_src ! The surface wind source of TKE [H Z2 T-3 ~> m3 s-3 or W m-2].
1507 real :: diag_wt ! The ratio of the current timestep to the diagnostic
1508 ! timestep (which may include 2 calls) [nondim].
1509 real :: H_to_Z ! The thickness to depth conversion factor, which in non-Boussinesq mode is
1510 ! based on the layer-averaged specific volume [Z H-1 ~> nondim or m3 kg-1]
1511 integer :: is, ie, nz, i
1512
1513180 is = G%isc ; ie = G%iec ; nz = GV%ke
1514180 diag_wt = dt * Idt_diag
1515
1516180 if (CS%omega_frac >= 1.0) absf = 2.0*CS%omega
151764980 do i=is,ie
151864800 U_star = U_star_2d(i,j)
1519
152064800 if (GV%Boussinesq .or. (.not.allocated(tv%SpV_avg))) then
152164800 H_to_Z = GV%H_to_Z
1522 else
15230 H_to_Z = GV%H_to_RZ * tv%SpV_avg(i,j,1)
1524 endif
1525
152664800 if (associated(fluxes%ustar_shelf) .and. associated(fluxes%frac_shelf_h)) then
15270 if (fluxes%frac_shelf_h(i,j) > 0.0) &
1528 U_star = (1.0 - fluxes%frac_shelf_h(i,j)) * U_star + &
15290 fluxes%frac_shelf_h(i,j) * fluxes%ustar_shelf(i,j)
1530 endif
1531
153264800 if (U_star < CS%ustar_min) U_star = CS%ustar_min
1533
153464800 if (CS%omega_frac < 1.0) then
1535 absf = 0.25*((abs(G%CoriolisBu(I,J)) + abs(G%CoriolisBu(I-1,J-1))) + &
15360 (abs(G%CoriolisBu(I,J-1)) + abs(G%CoriolisBu(I-1,J))))
15370 if (CS%omega_frac > 0.0) &
15380 absf = sqrt(CS%omega_frac*4.0*CS%omega**2 + (1.0-CS%omega_frac)*absf**2)
1539 endif
154064800 absf_Ustar = H_to_Z * absf / U_star
154164800 Idecay_len_TKE(i) = absf_Ustar * CS%TKE_decay
1542
1543! The first number in the denominator could be anywhere up to 16. The
1544! value of 3 was chosen to minimize the time-step dependence of the amount
1545! of shear-driven mixing in 10 days of a 1-degree global model, emphasizing
1546! the equatorial areas. Although it is not cast as a parameter, it should
1547! be considered an empirical parameter, and it might depend strongly on the
1548! number of sublayers in the mixed layer and their locations.
1549! This equation assumes that small & large scales contribute to mixed layer
1550! deepening at similar rates, even though small scales are dissipated more
1551! rapidly (implying they are less efficient).
1552! Ih = H_to_Z / (16.0*CS%vonKar*U_star*dt)
155364800 Ih = H_to_Z / (3.0*CS%vonKar*U_star*dt)
155464800 cMKE(1,i) = 4.0 * Ih ; cMKE(2,i) = absf_Ustar * Ih
1555
155664800 if (Idecay_len_TKE(i) > 0.0) then
155764800 exp_kh = exp(-htot(i)*Idecay_len_TKE(i))
1558 else
15590 exp_kh = 1.0
1560 endif
1561
1562! Here nstar is a function of the natural Rossby number 0.2/(1+0.2/Ro), based
1563! on a curve fit from the data of Wang (GRL, 2003).
1564! Note: Ro = 1.0/sqrt(0.5 * dt * (absf*htot(i))**3 / totEn)
156564800 if (Conv_En(i) < 0.0) Conv_En(i) = 0.0
156664800 if (cTKE(i,1) > 0.0) then ; TKE_CA = cTKE(i,1) ; else ; TKE_CA = 0.0 ; endif
156764800 if ((htot(i) >= h_CA(i)) .or. (TKE_CA == 0.0)) then
156859773 totEn_Z = (Conv_En(i) + TKE_CA)
1569
157059773 if (totEn_Z > 0.0) then
1571 nstar_FC = CS%nstar * totEn_Z / (totEn_Z + 0.2 * &
15724670 sqrt(0.5 * dt * (H_to_Z**2*(absf*htot(i))**3) * totEn_Z))
1573 else
157455103 nstar_FC = CS%nstar
1575 endif
157659773 nstar_CA = nstar_FC
1577 else
1578 ! This reconstructs the Buoyancy flux within the topmost htot of water.
15795027 if (Conv_En(i) > 0.0) then
15800 totEn_Z = (Conv_En(i) + TKE_CA * (htot(i) / h_CA(i)) )
1581 nstar_FC = CS%nstar * totEn_Z / (totEn_Z + 0.2 * &
15820 sqrt(0.5 * dt * (H_to_Z**2*(absf*htot(i))**3) * totEn_Z))
1583 else
15845027 nstar_FC = CS%nstar
1585 endif
1586
15875027 totEn_Z = (Conv_En(i) + TKE_CA)
15885027 if (TKE_CA > 0.0) then
1589 nstar_CA = CS%nstar * totEn_Z / (totEn_Z + 0.2 * &
15905027 sqrt(0.5 * dt * (H_to_Z**2*(absf*h_CA(i))**3) * totEn_Z))
1591 else
15920 nstar_CA = CS%nstar
1593 endif
1594 endif
1595
159664800 if (dKE_FC(i) + dKE_CA(i,1) > 0.0) then
15973349 if (htot(i) >= h_CA(i)) then
159886 MKE_rate_FC = 1.0 / (1.0 + htot(i)*(cMKE(1,i) + cMKE(2,i)*htot(i)) )
159986 MKE_rate_CA = MKE_rate_FC
1600 else
16013263 MKE_rate_FC = 1.0 / (1.0 + htot(i)*(cMKE(1,i) + cMKE(2,i)*htot(i)) )
16023263 MKE_rate_CA = 1.0 / (1.0 + h_CA(i)*(cMKE(1,i) + cMKE(2,i)*h_CA(i)) )
1603 endif
1604 else
1605 ! This branch just saves unnecessary calculations.
160661451 MKE_rate_FC = 1.0 ; MKE_rate_CA = 1.0
1607 endif
1608
160964800 dKE_conv = dKE_CA(i,1) * MKE_rate_CA + dKE_FC(i) * MKE_rate_FC
1610! At this point, it is assumed that cTKE is positive and stored in TKE_CA!
1611! Note: Removed factor of 2 in u*^3 terms.
161264800 if (GV%Boussinesq .or. GV%semi_Boussinesq .or. .not.(associated(fluxes%tau_mag))) then
1613 TKE(i) = (dt*CS%mstar)*((GV%Z_to_H*(U_star*U_Star*U_Star))*exp_kh) + &
161464800 (exp_kh * dKE_conv + nstar_FC*Conv_En(i) + nstar_CA * TKE_CA)
1615 else
1616 ! Note that GV%Z_to_H*U_star**3 = GV%RZ_to_H * fluxes%tau_mag(i,j) * U_star
1617 TKE(i) = (dt*CS%mstar) * ((GV%RZ_to_H * fluxes%tau_mag(i,j) * U_star)*exp_kh) + &
16180 (exp_kh * dKE_conv + nstar_FC*Conv_En(i) + nstar_CA * TKE_CA)
1619 endif
1620
162164800 if (CS%do_rivermix) then ! Add additional TKE at river mouths
16220 TKE(i) = TKE(i) + TKE_river(i)*dt*exp_kh
1623 endif
1624
162564980 if (CS%TKE_diagnostics) then
16260 if (GV%Boussinesq .or. GV%semi_Boussinesq .or. .not.(associated(fluxes%tau_mag))) then
16270 wind_TKE_src = CS%mstar*(GV%Z_to_H*U_star*U_Star*U_Star) * diag_wt
1628 else
16290 wind_TKE_src = CS%mstar*(GV%RZ_to_H * fluxes%tau_mag(i,j) * U_star) * diag_wt
1630 endif
1631 CS%diag_TKE_wind(i,j) = CS%diag_TKE_wind(i,j) + &
16320 ( wind_TKE_src + TKE_river(i) * diag_wt )
16330 CS%diag_TKE_RiBulk(i,j) = CS%diag_TKE_RiBulk(i,j) + dKE_conv*Idt_diag
1634 CS%diag_TKE_mech_decay(i,j) = CS%diag_TKE_mech_decay(i,j) + &
16350 (exp_kh-1.0)*(wind_TKE_src + dKE_conv*Idt_diag)
1636 CS%diag_TKE_conv(i,j) = CS%diag_TKE_conv(i,j) + &
16370 Idt_diag * (nstar_FC*Conv_En(i) + nstar_CA*TKE_CA)
1638 CS%diag_TKE_conv_decay(i,j) = CS%diag_TKE_conv_decay(i,j) + &
16390 Idt_diag * ((CS%nstar-nstar_FC)*Conv_En(i) + (CS%nstar-nstar_CA)*TKE_CA)
1640 CS%diag_TKE_conv_s2(i,j) = CS%diag_TKE_conv_s2(i,j) + &
16410 Idt_diag * (cTKE(i,1)-TKE_CA)
1642 endif
1643 enddo
1644
1645180end subroutine find_starting_TKE
1646
1647!> This subroutine calculates mechanically driven entrainment.
1648180subroutine mechanical_entrainment(h, d_eb, htot, Ttot, Stot, uhtot, vhtot, &
1649180 R0_tot, SpV0_tot, Rcv_tot, u, v, T, S, R0, SpV0, Rcv, eps, &
1650180 dR0_dT, dSpV0_dT, dRcv_dT, cMKE, Idt_diag, nsw, &
1651180 Pen_SW_bnd, opacity_band, TKE, &
1652180 Idecay_len_TKE, j, ksort, G, GV, US, CS)
1653 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
1654 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
1655 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
1656 real, dimension(SZI_(G),SZK0_(GV)), &
1657 intent(inout) :: h !< Layer thickness [H ~> m or kg m-2].
1658 real, dimension(SZI_(G),SZK_(GV)), &
1659 intent(inout) :: d_eb !< The downward increase across a layer in the
1660 !! layer in the entrainment from below [H ~> m or kg m-2].
1661 !! Positive values go with mass gain by a layer.
1662 real, dimension(SZI_(G)), intent(inout) :: htot !< The accumulated mixed layer thickness [H ~> m or kg m-2].
1663 real, dimension(SZI_(G)), intent(inout) :: Ttot !< The depth integrated mixed layer temperature
1664 !! [C H ~> degC m or degC kg m-2].
1665 real, dimension(SZI_(G)), intent(inout) :: Stot !< The depth integrated mixed layer salinity
1666 !! [S H ~> ppt m or ppt kg m-2].
1667 real, dimension(SZI_(G)), intent(inout) :: uhtot !< The depth integrated mixed layer zonal
1668 !! velocity [H L T-1 ~> m2 s-1 or kg m-1 s-1].
1669 real, dimension(SZI_(G)), intent(inout) :: vhtot !< The integrated mixed layer meridional
1670 !! velocity [H L T-1 ~> m2 s-1 or kg m-1 s-1].
1671 real, dimension(SZI_(G)), intent(inout) :: R0_tot !< The integrated mixed layer potential density
1672 !! referenced to 0 pressure [H R ~> kg m-2 or kg2 m-5].
1673 real, dimension(SZI_(G)), intent(inout) :: SpV0_tot !< The integrated mixed layer specific volume referenced
1674 !! to 0 pressure [H R-1 ~> m4 kg-1 or m].
1675 real, dimension(SZI_(G)), intent(inout) :: Rcv_tot !< The integrated mixed layer coordinate variable
1676 !! potential density [H R ~> kg m-2 or kg2 m-5].
1677 real, dimension(SZI_(G),SZK_(GV)), &
1678 intent(in) :: u !< Zonal velocities interpolated to h points [L T-1 ~> m s-1].
1679 real, dimension(SZI_(G),SZK_(GV)), &
1680 intent(in) :: v !< Zonal velocities interpolated to h points [L T-1 ~> m s-1].
1681 real, dimension(SZI_(G),SZK0_(GV)), &
1682 intent(in) :: T !< Layer temperatures [C ~> degC].
1683 real, dimension(SZI_(G),SZK0_(GV)), &
1684 intent(in) :: S !< Layer salinities [S ~> ppt].
1685 real, dimension(SZI_(G),SZK0_(GV)), &
1686 intent(in) :: R0 !< Potential density referenced to
1687 !! surface pressure [R ~> kg m-3].
1688 real, dimension(SZI_(G),SZK0_(GV)), &
1689 intent(in) :: SpV0 !< Specific volume referenced to
1690 !! surface pressure [R-1 ~> m3 kg-1].
1691 real, dimension(SZI_(G),SZK0_(GV)), &
1692 intent(in) :: Rcv !< The coordinate defining potential
1693 !! density [R ~> kg m-3].
1694 real, dimension(SZI_(G),SZK_(GV)), &
1695 intent(in) :: eps !< The negligibly small amount of water
1696 !! that will be left in each layer [H ~> m or kg m-2].
1697 real, dimension(SZI_(G)), intent(in) :: dR0_dT !< The partial derivative of R0 with respect to
1698 !! temperature [R C-1 ~> kg m-3 degC-1].
1699 real, dimension(SZI_(G)), intent(in) :: dSpV0_dT !< The partial derivative of SpV0 with respect to
1700 !! temperature [R-1 C-1 ~> m3 kg-1 degC-1].
1701 real, dimension(SZI_(G)), intent(in) :: dRcv_dT !< The partial derivative of Rcv with respect to
1702 !! temperature [R C-1 ~> kg m-3 degC-1].
1703 real, dimension(2,SZI_(G)), intent(in) :: cMKE !< Coefficients of HpE and HpE^2 used in calculating the
1704 !! denominator of MKE_rate; the two elements have differing
1705 !! units of [H-1 ~> m-1 or m2 kg-1] and [H-2 ~> m-2 or m4 kg-2].
1706 real, intent(in) :: Idt_diag !< The inverse of the accumulated diagnostic
1707 !! time interval [T-1 ~> s-1].
1708 integer, intent(in) :: nsw !< The number of bands of penetrating
1709 !! shortwave radiation.
1710 real, dimension(max(nsw,1),SZI_(G)), intent(inout) :: Pen_SW_bnd !< The penetrating shortwave
1711 !! heating at the sea surface in each penetrating
1712 !! band [C H ~> degC m or degC kg m-2].
1713 real, dimension(max(nsw,1),SZI_(G),SZK_(GV)), intent(in) :: opacity_band !< The opacity in each band of
1714 !! penetrating shortwave radiation [H-1 ~> m-1 or m2 kg-1].
1715 real, dimension(SZI_(G)), intent(inout) :: TKE !< The turbulent kinetic energy
1716 !! available for mixing over a time
1717 !! step [H Z2 T-2 ~> m3 s-2 or J m-2].
1718 real, dimension(SZI_(G)), intent(inout) :: Idecay_len_TKE !< The vertical TKE decay rate [H-1 ~> m-1 or m2 kg-1].
1719 integer, intent(in) :: j !< The j-index to work on.
1720 integer, dimension(SZI_(G),SZK_(GV)), &
1721 intent(in) :: ksort !< The density-sorted k-indices.
1722 type(bulkmixedlayer_CS), intent(inout) :: CS !< Bulk mixed layer control structure
1723
1724! This subroutine calculates mechanically driven entrainment.
1725
1726 ! Local variables
1727 real :: SW_trans ! The fraction of shortwave radiation that is not
1728 ! absorbed in a layer [nondim].
1729 real :: Pen_absorbed ! The amount of penetrative shortwave radiation
1730 ! that is absorbed in a layer [C H ~> degC m or degC kg m-2].
1731 real :: h_avail ! The thickness in a layer available for entrainment [H ~> m or kg m-2].
1732 real :: h_ent ! The thickness from a layer that is entrained [H ~> m or kg m-2].
1733 real :: h_min, h_max ! Limits on the solution for h_ent [H ~> m or kg m-2].
1734 real :: dh_Newt ! The Newton's method estimate of the change in
1735 ! h_ent between iterations [H ~> m or kg m-2].
1736 real :: MKE_rate ! The fraction of the energy in resolved shears
1737 ! within the mixed layer that will be eliminated
1738 ! within a timestep [nondim], 0 to 1.
1739 real :: HpE ! The current thickness plus entrainment [H ~> m or kg m-2].
1740 real :: g_H_2Rho0 ! Half the gravitational acceleration times the
1741 ! conversion from H to m divided by the mean density,
1742 ! in [Z2 T-2 H-1 R-1 ~> m4 s-2 kg-1 or m7 s-2 kg-2].
1743 real :: TKE_full_ent ! The TKE remaining if a layer is fully entrained
1744 ! [H Z2 T-2 ~> m3 s-2 or J m-2].
1745 real :: dRL ! Work required to mix water from the next layer
1746 ! across the mixed layer [Z2 T-2 ~> m2 s-2].
1747 real :: Pen_En_Contrib ! Penetrating SW contributions to the changes in
1748 ! TKE, divided by layer thickness in m [Z2 T-2 ~> m2 s-2].
1749 real :: Cpen1 ! A temporary variable [Z2 T-2 ~> m2 s-2].
1750 real :: dMKE ! A temporary variable related to the release of mean
1751 ! kinetic energy [H2 Z2 T-2 ~> m4 s-2 or kg2 m-2 s-2]
1752 real :: TKE_ent ! The TKE that remains if h_ent were entrained [H Z2 T-2 ~> m3 s-2 or J m-2]
1753 real :: TKE_ent1 ! The TKE that would remain, without considering the
1754 ! release of mean kinetic energy [H Z2 T-2 ~> m3 s-2 or J m-2]
1755 real :: dTKE_dh ! The partial derivative of TKE with h_ent [Z2 T-2 ~> m2 s-2]
1756 real :: Pen_dTKE_dh_Contrib ! The penetrating shortwave contribution to
1757 ! dTKE_dh [Z2 T-2 ~> m2 s-2].
1758 real :: EF4_val ! The result of EF4() (see later) [H-1 ~> m-1 or m2 kg-1].
1759 real :: h_neglect ! A thickness that is so small it is usually lost
1760 ! in roundoff and can be neglected [H ~> m or kg m-2].
1761 real :: dEF4_dh ! The partial derivative of EF4 with h [H-2 ~> m-2 or m4 kg-2].
1762 real :: Pen_En1 ! A nondimensional temporary variable [nondim].
1763 real :: kh, exp_kh, f1_kh ! Nondimensional temporary variables related to the
1764 ! fractional decay of TKE across a layer [nondim].
1765 real :: x1, e_x1 ! Nondimensional temporary variables related to the relative decay
1766 ! of TKE and SW radiation across a layer [nondim]
1767 real :: f1_x1, f2_x1, f3_x1 ! Exponential-related functions of x1 [nondim].
1768 real :: E_HxHpE ! Entrainment divided by the product of the new and old
1769 ! thicknesses [H-1 ~> m-1 or m2 kg-1].
1770 real :: Hmix_min ! The minimum mixed layer depth [H ~> m or kg m-2].
1771 real :: opacity ! The opacity of a layer in a band of shortwave radiation [H-1 ~> m-1 or m2 kg-1]
1772 real :: C1_3, C1_6, C1_24 ! 1/3, 1/6, and 1/24. [nondim]
1773 integer :: is, ie, nz, i, k, ks, itt, n
1774
1775180 C1_3 = 1.0/3.0 ; C1_6 = 1.0/6.0 ; C1_24 = 1.0/24.0
1776180 g_H_2Rho0 = (GV%g_Earth_Z_T2 * GV%H_to_Z) / (2.0 * GV%Rho0)
1777180 Hmix_min = CS%Hmix_min
1778180 h_neglect = GV%H_subroundoff
1779180 is = G%isc ; ie = G%iec ; nz = GV%ke
1780
17814140 do ks=1,nz
1782
17831429740 do i=is,ie ; if (ksort(i,ks) > 0) then
17841425600 k = ksort(i,ks)
1785
17861425600 h_avail = h(i,k) - eps(i,k)
17871425600 if ((h_avail > 0.) .and. ((TKE(i) > 0.) .or. (htot(i) < Hmix_min))) then
1788127567 if (CS%nonBous_energetics) then
17890 dRL = 0.5 * (GV%g_Earth_Z_T2 * GV%H_to_RZ) * (SpV0_tot(i) - SpV0(i,k)*htot(i))
1790 else
1791127567 dRL = g_H_2Rho0 * (R0(i,k)*htot(i) - R0_tot(i) )
1792 endif
1793 dMKE = CS%bulk_Ri_ML * 0.5 * &
1794127567 (((uhtot(i)-u(i,k)*htot(i))**2) + ((vhtot(i)-v(i,k)*htot(i))**2))
1795
1796! Find the TKE that would remain if the entire layer were entrained.
1797127567 kh = Idecay_len_TKE(i)*h_avail ; exp_kh = exp(-kh)
1798127567 if (kh >= 2.0e-5) then ; f1_kh = (1.0-exp_kh) / kh
179960262 else ; f1_kh = (1.0 - kh*(0.5 - C1_6*kh)) ; endif
1800
1801127567 Pen_En_Contrib = 0.0
1802255134 do n=1,nsw ; if (Pen_SW_bnd(n,i) > 0.0) then
18030 opacity = opacity_band(n,i,k)
1804! Two different forms are used here to make sure that only negative
1805! values are taken into exponentials to avoid excessively large
1806! numbers. They are, of course, mathematically identical.
18070 if (Idecay_len_TKE(i) > opacity) then
18080 x1 = (Idecay_len_TKE(i) - opacity) * h_avail
18090 if (x1 >= 2.0e-5) then
18100 e_x1 = exp(-x1) ; f1_x1 = ((1.0-e_x1)/(x1))
18110 f3_x1 = ((e_x1-(1.0-x1))/(x1*x1))
1812 else
18130 f1_x1 = (1.0 - x1*(0.5 - C1_6*x1))
18140 f3_x1 = (0.5 - x1*(C1_6 - C1_24*x1))
1815 endif
1816
1817 Pen_En1 = exp(-opacity*h_avail) * &
18180 ((1.0+opacity*htot(i))*f1_x1 + opacity*h_avail*f3_x1)
1819 else
18200 x1 = (opacity - Idecay_len_TKE(i)) * h_avail
18210 if (x1 >= 2.0e-5) then
18220 e_x1 = exp(-x1) ; f1_x1 = ((1.0-e_x1)/(x1))
18230 f2_x1 = ((1.0-(1.0+x1)*e_x1)/(x1*x1))
1824 else
18250 f1_x1 = (1.0 - x1*(0.5 - C1_6*x1))
18260 f2_x1 = (0.5 - x1*(C1_3 - 0.125*x1))
1827 endif
1828
1829 Pen_En1 = exp_kh * ((1.0+opacity*htot(i))*f1_x1 + &
18300 opacity*h_avail*f2_x1)
1831 endif
18320 if (CS%nonBous_energetics) then
1833 Pen_En_Contrib = Pen_En_Contrib - &
18340 (0.5 * (GV%g_Earth_Z_T2 * GV%H_to_RZ) * dSpV0_dT(i)*Pen_SW_bnd(n,i)) * (Pen_En1 - f1_kh)
1835 else
1836 Pen_En_Contrib = Pen_En_Contrib + &
18370 (g_H_2Rho0*dR0_dT(i)*Pen_SW_bnd(n,i)) * (Pen_En1 - f1_kh)
1838 endif
1839 endif ; enddo
1840
1841127567 HpE = htot(i)+h_avail
1842127567 MKE_rate = 1.0/(1.0 + (cMKE(1,i)*HpE + cMKE(2,i)*HpE**2))
1843127567 EF4_val = EF4(htot(i)+h_neglect,h_avail,Idecay_len_TKE(i))
1844 TKE_full_ent = (exp_kh*TKE(i) - h_avail*(dRL*f1_kh + Pen_En_Contrib)) + &
1845127567 MKE_rate*dMKE*EF4_val
1846127567 if ((TKE_full_ent >= 0.0) .or. (h_avail+htot(i) <= Hmix_min)) then
1847 ! The layer will be fully entrained.
184881492 h_ent = h_avail
1849
185081492 if (CS%TKE_diagnostics) then
18510 E_HxHpE = h_ent / ((htot(i)+h_neglect)*(htot(i)+h_ent+h_neglect))
1852 CS%diag_TKE_mech_decay(i,j) = CS%diag_TKE_mech_decay(i,j) + &
1853 Idt_diag * ((exp_kh-1.0)* TKE(i) + h_ent*dRL*(1.0-f1_kh) + &
18540 MKE_rate*dMKE*(EF4_val-E_HxHpE))
18550 CS%diag_TKE_mixing(i,j) = CS%diag_TKE_mixing(i,j) - Idt_diag*h_ent*dRL
1856 CS%diag_TKE_pen_SW(i,j) = CS%diag_TKE_pen_SW(i,j) - &
18570 Idt_diag*h_ent*Pen_En_Contrib
1858 CS%diag_TKE_RiBulk(i,j) = CS%diag_TKE_RiBulk(i,j) + &
18590 Idt_diag*MKE_rate*dMKE*E_HxHpE
1860 endif
1861
186281492 TKE(i) = TKE_full_ent
1863
186481492 if (TKE(i) <= 0.0) TKE(i) = CS%mech_TKE_floor
1865 else
1866! The layer is only partially entrained. The amount that will be
1867! entrained is determined iteratively. No further layers will be
1868! entrained.
186946075 h_min = 0.0 ; h_max = h_avail
187046075 if (TKE(i) <= 0.0) then
18710 h_ent = 0.0
1872 else
187346075 h_ent = h_avail * TKE(i) / (TKE(i) - TKE_full_ent)
1874
1875330432 do itt=1,15
1876 ! Evaluate the TKE that would remain if h_ent were entrained.
1877
1878330432 kh = Idecay_len_TKE(i)*h_ent ; exp_kh = exp(-kh)
1879330432 if (kh >= 2.0e-5) then
1880326626 f1_kh = (1.0-exp_kh) / kh
1881 else
18823806 f1_kh = (1.0 - kh*(0.5 - C1_6*kh))
1883 endif
1884
1885
1886330432 Pen_En_Contrib = 0.0 ; Pen_dTKE_dh_Contrib = 0.0
1887660864 do n=1,nsw ; if (Pen_SW_bnd(n,i) > 0.0) then
1888 ! Two different forms are used here to make sure that only negative
1889 ! values are taken into exponentials to avoid excessively large
1890 ! numbers. They are, of course, mathematically identical.
18910 opacity = opacity_band(n,i,k)
18920 SW_trans = exp(-h_ent*opacity)
18930 if (Idecay_len_TKE(i) > opacity) then
18940 x1 = (Idecay_len_TKE(i) - opacity) * h_ent
18950 if (x1 >= 2.0e-5) then
18960 e_x1 = exp(-x1) ; f1_x1 = ((1.0-e_x1)/(x1))
18970 f3_x1 = ((e_x1-(1.0-x1))/(x1*x1))
1898 else
18990 f1_x1 = (1.0 - x1*(0.5 - C1_6*x1))
19000 f3_x1 = (0.5 - x1*(C1_6 - C1_24*x1))
1901 endif
1902 Pen_En1 = SW_trans * ((1.0+opacity*htot(i))*f1_x1 + &
19030 opacity*h_ent*f3_x1)
1904 else
19050 x1 = (opacity - Idecay_len_TKE(i)) * h_ent
19060 if (x1 >= 2.0e-5) then
19070 e_x1 = exp(-x1) ; f1_x1 = ((1.0-e_x1)/(x1))
19080 f2_x1 = ((1.0-(1.0+x1)*e_x1)/(x1*x1))
1909 else
19100 f1_x1 = (1.0 - x1*(0.5 - C1_6*x1))
19110 f2_x1 = (0.5 - x1*(C1_3 - 0.125*x1))
1912 endif
1913
1914 Pen_En1 = exp_kh * ((1.0+opacity*htot(i))*f1_x1 + &
19150 opacity*h_ent*f2_x1)
1916 endif
19170 if (CS%nonBous_energetics) then
19180 Cpen1 = -0.5 * (GV%g_Earth_Z_T2 * GV%H_to_RZ) * dSpV0_dT(i) * Pen_SW_bnd(n,i)
1919 else
19200 Cpen1 = g_H_2Rho0 * dR0_dT(i) * Pen_SW_bnd(n,i)
1921 endif
19220 Pen_En_Contrib = Pen_En_Contrib + Cpen1*(Pen_En1 - f1_kh)
1923 Pen_dTKE_dh_Contrib = Pen_dTKE_dh_Contrib + &
19240 Cpen1*((1.0-SW_trans) - opacity*(htot(i) + h_ent)*SW_trans)
1925 endif ; enddo ! (Pen_SW_bnd(n,i) > 0.0)
1926
1927330432 TKE_ent1 = exp_kh* TKE(i) - h_ent*(dRL*f1_kh + Pen_En_Contrib)
1928330432 EF4_val = EF4(htot(i)+h_neglect,h_ent,Idecay_len_TKE(i),dEF4_dh)
1929330432 HpE = htot(i)+h_ent
1930330432 MKE_rate = 1.0/(1.0 + (cMKE(1,i)*HpE + cMKE(2,i)*HpE**2))
1931330432 TKE_ent = TKE_ent1 + dMKE*EF4_val*MKE_rate
1932 ! TKE_ent is the TKE that would remain if h_ent were entrained.
1933
1934 dTKE_dh = ((-Idecay_len_TKE(i)*TKE_ent1 - dRL) + &
1935 Pen_dTKE_dh_Contrib) + dMKE * MKE_rate* &
1936330432 (dEF4_dh - EF4_val*MKE_rate*(cMKE(1,i)+2.0*cMKE(2,i)*HpE))
1937 ! dh_Newt = -TKE_ent / dTKE_dh
1938 ! Bisect if the Newton's method prediction is outside of the bounded range.
1939330432 if (TKE_ent > 0.0) then
1940219643 if ((h_max-h_ent)*(-dTKE_dh) > TKE_ent) then
1941219643 dh_Newt = -TKE_ent / dTKE_dh
1942 else
19430 dh_Newt = 0.5*(h_max-h_ent)
1944 endif
1945219643 h_min = h_ent
1946 else
1947110789 if ((h_min-h_ent)*(-dTKE_dh) < TKE_ent) then
194848859 dh_Newt = -TKE_ent / dTKE_dh
1949 else
195061930 dh_Newt = 0.5*(h_min-h_ent)
1951 endif
1952110789 h_max = h_ent
1953 endif
1954330432 h_ent = h_ent + dh_Newt
1955
1956330432 if (ABS(dh_Newt) < 0.2*GV%Angstrom_H) exit
1957 enddo
1958 endif
1959
196046075 if (h_ent < Hmix_min-htot(i)) h_ent = Hmix_min - htot(i)
1961
196246075 if (CS%TKE_diagnostics) then
19630 HpE = htot(i)+h_ent
19640 MKE_rate = 1.0/(1.0 + cMKE(1,i)*HpE + cMKE(2,i)*HpE**2)
19650 EF4_val = EF4(htot(i)+h_neglect,h_ent,Idecay_len_TKE(i))
1966
19670 E_HxHpE = h_ent / ((htot(i)+h_neglect)*(HpE+h_neglect))
1968 CS%diag_TKE_mech_decay(i,j) = CS%diag_TKE_mech_decay(i,j) + &
1969 Idt_diag * ((exp_kh-1.0)* TKE(i) + h_ent*dRL*(1.0-f1_kh) + &
19700 dMKE*MKE_rate*(EF4_val-E_HxHpE))
19710 CS%diag_TKE_mixing(i,j) = CS%diag_TKE_mixing(i,j) - Idt_diag*h_ent*dRL
19720 CS%diag_TKE_pen_SW(i,j) = CS%diag_TKE_pen_SW(i,j) - Idt_diag*h_ent*Pen_En_Contrib
19730 CS%diag_TKE_RiBulk(i,j) = CS%diag_TKE_RiBulk(i,j) + Idt_diag*dMKE*MKE_rate*E_HxHpE
1974 endif
1975
197646075 TKE(i) = 0.0
1977 endif ! TKE_full_ent > 0.0
1978
1979127567 Pen_absorbed = 0.0
1980255134 do n=1,nsw ; if (Pen_SW_bnd(n,i) > 0.0) then
19810 SW_trans = exp(-h_ent*opacity_band(n,i,k))
19820 Pen_absorbed = Pen_absorbed + Pen_SW_bnd(n,i) * (1.0 - SW_trans)
19830 Pen_SW_bnd(n,i) = Pen_SW_bnd(n,i) * SW_trans
1984 endif ; enddo
1985
1986127567 htot(i) = htot(i) + h_ent
1987127567 if (CS%nonBous_energetics) then
19880 SpV0_tot(i) = SpV0_tot(i) + (h_ent * SpV0(i,k) + Pen_absorbed*dSpV0_dT(i))
1989 else
1990127567 R0_tot(i) = R0_tot(i) + (h_ent * R0(i,k) + Pen_absorbed*dR0_dT(i))
1991 endif
1992127567 h(i,k) = h(i,k) - h_ent
1993127567 d_eb(i,k) = d_eb(i,k) - h_ent
1994
1995127567 Stot(i) = Stot(i) + h_ent * S(i,k)
1996127567 Ttot(i) = Ttot(i) + (h_ent * T(i,k) + Pen_absorbed)
1997127567 Rcv_tot(i) = Rcv_tot(i) + (h_ent*Rcv(i,k) + Pen_absorbed*dRcv_dT(i))
1998
1999127567 uhtot(i) = uhtot(i) + u(i,k)*h_ent
2000127567 vhtot(i) = vhtot(i) + v(i,k)*h_ent
2001 endif ! h_avail > 0.0 .and. TKE(i) > 0.0
2002
2003 endif ; enddo ! i loop
2004 enddo ! k loop
2005
2006180end subroutine mechanical_entrainment
2007
2008!> This subroutine generates an array of indices that are sorted by layer
2009!! density.
20100subroutine sort_ML(h, R0, SpV0, eps, G, GV, CS, ksort)
2011 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
2012 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
2013 real, dimension(SZI_(G),SZK0_(GV)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2].
2014 real, dimension(SZI_(G),SZK0_(GV)), intent(in) :: R0 !< The potential density used to sort
2015 !! the layers [R ~> kg m-3].
2016 real, dimension(SZI_(G),SZK0_(GV)), intent(in) :: SpV0 !< Specific volume referenced to
2017 !! surface pressure [R-1 ~> m3 kg-1]
2018 real, dimension(SZI_(G),SZK_(GV)), intent(in) :: eps !< The (small) thickness that must
2019 !! remain in each layer [H ~> m or kg m-2].
2020 type(bulkmixedlayer_CS), intent(in) :: CS !< Bulk mixed layer control structure
2021 integer, dimension(SZI_(G),SZK_(GV)), intent(out) :: ksort !< The k-index to use in the sort.
2022
2023 ! Local variables
20240 real :: R0sort(SZI_(G),SZK_(GV)) ! The sorted potential density [R ~> kg m-3]
20250 real :: SpV0sort(SZI_(G),SZK_(GV)) ! The sorted specific volume [R-1 ~> m3 kg-1]
20260 integer :: nsort(SZI_(G)) ! The number of layers left to sort
20270 logical :: done_sorting(SZI_(G))
2028 integer :: i, k, ks, is, ie, nz, nkmb
2029
20300 is = G%isc ; ie = G%iec ; nz = GV%ke
20310 nkmb = CS%nkml+CS%nkbl
2032
2033 ! Come up with a sorted index list of layers with increasing R0.
2034 ! Assume that the layers below nkmb are already stably stratified.
2035 ! Only layers that are thicker than eps are in the list. Extra elements
2036 ! have an index of -1.
2037
2038 ! This is coded using straight insertion, on the assumption that the
2039 ! layers are usually in the right order (or massless) anyway.
2040
20410 do k=1,nz ; do i=is,ie ; ksort(i,k) = -1 ; enddo ; enddo
2042
20430 do i=is,ie ; nsort(i) = 0 ; done_sorting(i) = .false. ; enddo
2044
20450 if (CS%nonBous_energetics) then
20460 do k=1,nz ; do i=is,ie ; if (h(i,k) > eps(i,k)) then
20470 if (done_sorting(i)) then ; ks = nsort(i) ; else
20480 do ks=nsort(i),1,-1
20490 if (SpV0(i,k) <= SpV0sort(i,ks)) exit
20500 SpV0sort(i,ks+1) = SpV0sort(i,ks) ; ksort(i,ks+1) = ksort(i,ks)
2051 enddo
20520 if ((k > nkmb) .and. (ks == nsort(i))) done_sorting(i) = .true.
2053 endif
2054
20550 ksort(i,ks+1) = k
20560 SpV0sort(i,ks+1) = SpV0(i,k)
20570 nsort(i) = nsort(i) + 1
2058 endif ; enddo ; enddo
2059 else
20600 do k=1,nz ; do i=is,ie ; if (h(i,k) > eps(i,k)) then
20610 if (done_sorting(i)) then ; ks = nsort(i) ; else
20620 do ks=nsort(i),1,-1
20630 if (R0(i,k) >= R0sort(i,ks)) exit
20640 R0sort(i,ks+1) = R0sort(i,ks) ; ksort(i,ks+1) = ksort(i,ks)
2065 enddo
20660 if ((k > nkmb) .and. (ks == nsort(i))) done_sorting(i) = .true.
2067 endif
2068
20690 ksort(i,ks+1) = k
20700 R0sort(i,ks+1) = R0(i,k)
20710 nsort(i) = nsort(i) + 1
2072 endif ; enddo ; enddo
2073 endif
2074
20750end subroutine sort_ML
2076
2077!> This subroutine actually moves properties between layers to achieve a
2078!! resorted state, with all of the resorted water either moved into the correct
2079!! interior layers or in the top nkmb layers.
20800subroutine resort_ML(h, T, S, R0, SpV0, Rcv, RcvTgt, eps, d_ea, d_eb, ksort, G, GV, CS, &
20810 dR0_dT, dR0_dS, dSpV0_dT, dSpV0_dS, dRcv_dT, dRcv_dS)
2082 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
2083 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid
2084 !! structure.
2085 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2].
2086 !! Layer 0 is the new mixed layer.
2087 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Layer temperatures [C ~> degC].
2088 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Layer salinities [S ~> ppt].
2089 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: R0 !< Potential density referenced to
2090 !! surface pressure [R ~> kg m-3].
2091 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: SpV0 !< Specific volume referenced to
2092 !! surface pressure [R-1 ~> m3 kg-1]
2093 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: Rcv !< The coordinate defining
2094 !! potential density [R ~> kg m-3].
2095 real, dimension(SZK_(GV)), intent(in) :: RcvTgt !< The target value of Rcv for each
2096 !! layer [R ~> kg m-3].
2097 real, dimension(SZI_(G),SZK_(GV)), intent(inout) :: eps !< The (small) thickness that must
2098 !! remain in each layer [H ~> m or kg m-2].
2099 real, dimension(SZI_(G),SZK_(GV)), intent(inout) :: d_ea !< The upward increase across a
2100 !! layer in the entrainment from
2101 !! above [H ~> m or kg m-2].
2102 !! Positive d_ea goes with layer
2103 !! thickness increases.
2104 real, dimension(SZI_(G),SZK_(GV)), intent(inout) :: d_eb !< The downward increase across a
2105 !! layer in the entrainment from
2106 !! below [H ~> m or kg m-2]. Positive values go
2107 !! with mass gain by a layer.
2108 integer, dimension(SZI_(G),SZK_(GV)), intent(in) :: ksort !< The density-sorted k-indices.
2109 type(bulkmixedlayer_CS), intent(in) :: CS !< Bulk mixed layer control structure
2110 real, dimension(SZI_(G)), intent(in) :: dR0_dT !< The partial derivative of
2111 !! potential density referenced
2112 !! to the surface with potential
2113 !! temperature [R C-1 ~> kg m-3 degC-1].
2114 real, dimension(SZI_(G)), intent(in) :: dR0_dS !< The partial derivative of
2115 !! potential density referenced
2116 !! to the surface with salinity,
2117 !! [R S-1 ~> kg m-3 ppt-1].
2118 real, dimension(SZI_(G)), intent(in) :: dSpV0_dT !< The partial derivative of SpV0 with respect
2119 !! to temperature [R-1 C-1 ~> m3 kg-1 degC-1]
2120 real, dimension(SZI_(G)), intent(in) :: dSpV0_dS !< The partial derivative of SpV0 with respect
2121 !! to salinity [R-1 S-1 ~> m3 kg-1 ppt-1]
2122 real, dimension(SZI_(G)), intent(in) :: dRcv_dT !< The partial derivative of
2123 !! coordinate defining potential
2124 !! density with potential
2125 !! temperature [R C-1 ~> kg m-3 degC-1].
2126 real, dimension(SZI_(G)), intent(in) :: dRcv_dS !< The partial derivative of
2127 !! coordinate defining potential
2128 !! density with salinity,
2129 !! [R S-1 ~> kg m-3 ppt-1].
2130
2131! If there are no massive light layers above the deepest of the mixed- and
2132! buffer layers, do nothing (except perhaps to reshuffle these layers).
2133! If there are nkbl or fewer layers above the deepest mixed- or buffer-
2134! layers, move them (in sorted order) into the buffer layers, even if they
2135! were previously interior layers.
2136! If there are interior layers that are intermediate in density (both in-situ
2137! and the coordinate density (sigma-2)) between the newly forming mixed layer
2138! and a residual buffer- or mixed layer, and the number of massive layers above
2139! the deepest massive buffer or mixed layer is greater than nkbl, then split
2140! those buffer layers into pieces that match the target density of the two
2141! nearest interior layers.
2142! Otherwise, if there are more than nkbl+1 remaining massive layers
2143
2144 ! Local variables
2145 real :: h_move ! The thickness of water being moved between layers [H ~> m or kg m-2]
2146 real :: h_tgt_old ! The previous thickness of the recipient layer [H ~> m or kg m-2]
2147 real :: I_hnew ! The inverse of a new layer thickness [H-1 ~> m-1 or m2 kg-1]
2148 real :: dT_dS_wt2 ! The square of the relative weighting of temperature and salinity changes
2149 ! when extrapolating to match a target density [C2 S-2 ~> degC2 ppt-2]
2150 real :: dT_dR ! The ratio of temperature changes to density changes when
2151 ! extrapolating [C R-1 ~> degC m3 kg-1]
2152 real :: dS_dR ! The ratio of salinity changes to density changes when
2153 ! extrapolating [S R-1 ~> ppt m3 kg-1]
2154 real :: I_denom ! A work variable with units of [S2 R-2 ~> ppt2 m6 kg-2].
2155 real :: Rcv_int ! The target coordinate density of an interior layer [R ~> kg m-3]
2156 real :: T_up, T_dn ! Temperatures projected to match the target densities of two layers [C ~> degC]
2157 real :: S_up, S_dn ! Salinities projected to match the target densities of two layers [S ~> ppt]
2158 real :: R0_up, R0_dn ! Potential densities projected to match the target coordinate
2159 ! densities of two layers [R ~> kg m-3]
2160 real :: SpV0_up, SpV0_dn ! Specific volumes projected to be consistent with the target coordinate
2161 ! densities of two layers [R-1 ~> m3 kg-1]
2162 real :: I_hup, I_hdn ! Inverse of the new thicknesses of the two layers [H-1 ~> m-1 or m2 kg-1]
2163 real :: h_to_up, h_to_dn ! Thickness transferred to two layers [H ~> m or kg m-2]
2164 real :: wt_dn ! Fraction of the thickness transferred to the deeper layer [nondim]
2165 real :: dR1, dR2 ! Density difference with the target densities of two layers [R ~> kg m-3]
2166 real :: dPE, min_dPE ! Values proportional to the potential energy change due to the merging of a
2167 ! pair of layers [R H2 ~> kg m-1 or kg3 m-7] or [R-1 H2 ~> m5 kg-1 or kg m-1]
2168 real :: hmin, min_hmin ! The thickness of the thinnest layer [H ~> m or kg m-2]
21690 real :: h_tmp(SZK_(GV)) ! A copy of the original layer thicknesses [H ~> m or kg m-2]
21700 real :: R0_tmp(SZK_(GV)) ! A copy of the original layer potential densities [R ~> kg m-3]
21710 real :: SpV0_tmp(SZK_(GV)) ! A copy of the original layer specific volumes [R ~> kg m-3]
21720 real :: T_tmp(SZK_(GV)) ! A copy of the original layer temperatures [C ~> degC]
21730 real :: S_tmp(SZK_(GV)) ! A copy of the original layer salinities [S ~> ppt]
21740 real :: Rcv_tmp(SZK_(GV)) ! A copy of the original layer coordinate densities [R ~> kg m-3]
2175 integer :: ks_min
2176 logical :: sorted, leave_in_layer
21770 integer :: ks_deep(SZI_(G)), k_count(SZI_(G)), ks2_reverse(SZI_(G), SZK_(GV))
21780 integer :: ks2(SZK_(GV))
2179 integer :: i, k, ks, is, ie, nz, k1, k2, k_tgt, k_src, k_int_top
2180 integer :: nks, nkmb, num_interior, top_interior_ks
2181
21820 is = G%isc ; ie = G%iec ; nz = GV%ke
21830 nkmb = CS%nkml+CS%nkbl
2184
21850 dT_dS_wt2 = CS%dT_dS_wt**2
2186
2187! Find out how many massive layers are above the deepest buffer or mixed layer.
21880 do i=is,ie ; ks_deep(i) = -1 ; k_count(i) = 0 ; enddo
21890 do ks=nz,1,-1 ; do i=is,ie ; if (ksort(i,ks) > 0) then
21900 k = ksort(i,ks)
2191
21920 if (h(i,k) > eps(i,k)) then
21930 if (ks_deep(i) == -1) then
21940 if (k <= nkmb) then
21950 ks_deep(i) = ks ; k_count(i) = k_count(i) + 1
21960 ks2_reverse(i,k_count(i)) = k
2197 endif
2198 else
21990 k_count(i) = k_count(i) + 1
22000 ks2_reverse(i,k_count(i)) = k
2201 endif
2202 endif
2203 endif ; enddo ; enddo
2204
22050 do i=is,ie ; if (k_count(i) > 1) then
2206 ! This column might need to be reshuffled.
22070 nks = k_count(i)
2208
2209 ! Put ks2 in the right order and check whether reshuffling is needed.
22100 sorted = .true.
22110 ks2(nks) = ks2_reverse(i,1)
22120 do ks=nks-1,1,-1
22130 ks2(ks) = ks2_reverse(i,1+nks-ks)
22140 if (ks2(ks) > ks2(ks+1)) sorted = .false.
2215 enddo
2216
2217 ! Go to the next column of no reshuffling is needed.
22180 if (sorted) cycle
2219
2220 ! Find out how many interior layers are being reshuffled. If none,
2221 ! then this is a simple swapping procedure.
22220 num_interior = 0 ; top_interior_ks = 0
22230 do ks=nks,1,-1 ; if (ks2(ks) > nkmb) then
22240 num_interior = num_interior+1 ; top_interior_ks = ks
2225 endif ; enddo
2226
22270 if (num_interior >= 1) then
2228 ! Find the lightest interior layer with a target coordinate density
2229 ! greater than the newly forming mixed layer.
22300 do k=nkmb+1,nz ; if (Rcv(i,0) < RcvTgt(k)) exit ; enddo
22310 k_int_top = k ; Rcv_int = RcvTgt(k)
2232
22330 I_denom = 1.0 / (dRcv_dS(i)**2 + dT_dS_wt2*dRcv_dT(i)**2)
22340 dT_dR = dT_dS_wt2*dRcv_dT(i) * I_denom
22350 dS_dR = dRcv_dS(i) * I_denom
2236
2237
2238 ! Examine whether layers can be split out of existence. Stop when there
2239 ! is a layer that cannot be handled this way, or when the topmost formerly
2240 ! interior layer has been dealt with.
22410 do ks = nks,top_interior_ks,-1
22420 k = ks2(ks)
22430 leave_in_layer = .false.
22440 if ((k > nkmb) .and. (Rcv(i,k) <= RcvTgt(k))) then
22450 if (RcvTgt(k)-Rcv(i,k) < CS%BL_split_rho_tol*(RcvTgt(k) - RcvTgt(k-1))) &
22460 leave_in_layer = .true.
22470 elseif (k > nkmb) then
22480 if (Rcv(i,k)-RcvTgt(k) < CS%BL_split_rho_tol*(RcvTgt(k+1) - RcvTgt(k))) &
22490 leave_in_layer = .true.
2250 endif
2251
22520 if (leave_in_layer) then
2253 ! Just drop this layer from the sorted list.
22540 nks = nks-1
22550 elseif (Rcv(i,k) < Rcv_int) then
2256 ! There is no interior layer with a target density that is intermediate
2257 ! between this layer and the mixed layer.
22580 exit
2259 else
2260 ! Try splitting the layer between two interior isopycnal layers.
2261 ! Find the target densities that bracket this layer.
22620 do k2=k_int_top+1,nz ; if (Rcv(i,k) < RcvTgt(k2)) exit ; enddo
22630 if (k2>nz) exit
2264
2265 ! This layer is bracketed in density between layers k2-1 and k2.
2266
22670 dR1 = (RcvTgt(k2-1) - Rcv(i,k)) ; dR2 = (RcvTgt(k2) - Rcv(i,k))
22680 T_up = T(i,k) + dT_dR * dR1
22690 S_up = S(i,k) + dS_dR * dR1
22700 T_dn = T(i,k) + dT_dR * dR2
22710 S_dn = S(i,k) + dS_dR * dR2
2272
22730 if (CS%nonBous_energetics) then
22740 SpV0_up = SpV0(i,k) + (dT_dR*dSpV0_dT(i) + dS_dR*dSpV0_dS(i)) * dR1
22750 SpV0_dn = SpV0(i,k) + (dT_dR*dSpV0_dT(i) + dS_dR*dSpV0_dS(i)) * dR2
2276
2277 ! Make sure the new properties are acceptable, and avoid creating obviously unstable profiles.
22780 if ((SpV0_up < SpV0(i,0)) .or. (SpV0_dn < SpV0(i,0))) exit
2279 else
22800 R0_up = R0(i,k) + (dT_dR*dR0_dT(i) + dS_dR*dR0_dS(i)) * dR1
22810 R0_dn = R0(i,k) + (dT_dR*dR0_dT(i) + dS_dR*dR0_dS(i)) * dR2
2282
2283 ! Make sure the new properties are acceptable, and avoid creating obviously unstable profiles.
22840 if ((R0_up > R0(i,0)) .or. (R0_dn > R0(i,0))) exit
2285 endif
2286
22870 wt_dn = (Rcv(i,k) - RcvTgt(k2-1)) / (RcvTgt(k2) - RcvTgt(k2-1))
22880 h_to_up = (h(i,k)-eps(i,k)) * (1.0 - wt_dn)
22890 h_to_dn = (h(i,k)-eps(i,k)) * wt_dn
2290
22910 I_hup = 1.0 / (h(i,k2-1) + h_to_up)
22920 I_hdn = 1.0 / (h(i,k2) + h_to_dn)
22930 if (CS%nonBous_energetics) then
22940 SpV0(i,k2-1) = (SpV0(i,k2)*h(i,k2-1) + SpV0_up*h_to_up) * I_hup
22950 SpV0(i,k2) = (SpV0(i,k2)*h(i,k2) + SpV0_dn*h_to_dn) * I_hdn
2296 else
22970 R0(i,k2-1) = (R0(i,k2)*h(i,k2-1) + R0_up*h_to_up) * I_hup
22980 R0(i,k2) = (R0(i,k2)*h(i,k2) + R0_dn*h_to_dn) * I_hdn
2299 endif
2300
23010 T(i,k2-1) = (T(i,k2)*h(i,k2-1) + T_up*h_to_up) * I_hup
23020 T(i,k2) = (T(i,k2)*h(i,k2) + T_dn*h_to_dn) * I_hdn
23030 S(i,k2-1) = (S(i,k2)*h(i,k2-1) + S_up*h_to_up) * I_hup
23040 S(i,k2) = (S(i,k2)*h(i,k2) + S_dn*h_to_dn) * I_hdn
23050 Rcv(i,k2-1) = (Rcv(i,k2)*h(i,k2-1) + RcvTgt(k2-1)*h_to_up) * I_hup
23060 Rcv(i,k2) = (Rcv(i,k2)*h(i,k2) + RcvTgt(k2)*h_to_dn) * I_hdn
2307
23080 h(i,k) = eps(i,k)
23090 h(i,k2) = h(i,k2) + h_to_dn
23100 h(i,k2-1) = h(i,k2-1) + h_to_up
2311
23120 if (k > k2-1) then
23130 d_eb(i,k) = d_eb(i,k) - h_to_up
23140 d_eb(i,k2-1) = d_eb(i,k2-1) + h_to_up
23150 elseif (k < k2-1) then
23160 d_ea(i,k) = d_ea(i,k) - h_to_up
23170 d_ea(i,k2-1) = d_ea(i,k2-1) + h_to_up
2318 endif
23190 if (k > k2) then
23200 d_eb(i,k) = d_eb(i,k) - h_to_dn
23210 d_eb(i,k2) = d_eb(i,k2) + h_to_dn
23220 elseif (k < k2) then
23230 d_ea(i,k) = d_ea(i,k) - h_to_dn
23240 d_ea(i,k2) = d_ea(i,k2) + h_to_dn
2325 endif
23260 nks = nks-1
2327 endif
2328 enddo
2329 endif
2330
23310 do while (nks > nkmb)
2332 ! Having already tried to move surface layers into the interior, there
2333 ! are still too many layers, and layers must be merged until nks=nkmb.
2334 ! Examine every merger of a layer with its neighbors, and merge the ones
2335 ! that increase the potential energy the least. If there are layers
2336 ! with (apparently?) negative potential energy change, choose the one
2337 ! with the smallest total thickness. Repeat until nkmb layers remain.
2338 ! Choose the smaller value for the remaining index for convenience.
2339
23400 ks_min = -1 ; min_dPE = 1.0 ; min_hmin = 0.0
23410 do ks=1,nks-1
23420 k1 = ks2(ks) ; k2 = ks2(ks+1)
23430 if (CS%nonBous_energetics) then
23440 dPE = max(0.0, (SpV0(i,k1) - SpV0(i,k2)) * (h(i,k1) * h(i,k2)))
2345 else
23460 dPE = max(0.0, (R0(i,k2) - R0(i,k1)) * h(i,k1) * h(i,k2))
2347 endif
23480 hmin = min(h(i,k1)-eps(i,k1), h(i,k2)-eps(i,k2))
23490 if ((ks_min < 0) .or. (dPE < min_dPE) .or. &
23500 ((dPE <= 0.0) .and. (hmin < min_hmin))) then
23510 ks_min = ks ; min_dPE = dPE ; min_hmin = hmin
2352 endif
2353 enddo
2354
2355 ! Now merge the two layers that do the least damage.
23560 k1 = ks2(ks_min) ; k2 = ks2(ks_min+1)
23570 if (k1 < k2) then ; k_tgt = k1 ; k_src = k2
23580 else ; k_tgt = k2 ; k_src = k1 ; ks2(ks_min) = k2 ; endif
2359
23600 h_tgt_old = h(i,k_tgt)
23610 h_move = h(i,k_src)-eps(i,k_src)
23620 h(i,k_src) = eps(i,k_src)
23630 h(i,k_tgt) = h(i,k_tgt) + h_move
23640 I_hnew = 1.0 / (h(i,k_tgt))
23650 if (CS%nonBous_energetics) then
23660 SpV0(i,k_tgt) = (SpV0(i,k_tgt)*h_tgt_old + SpV0(i,k_src)*h_move) * I_hnew
2367 else
23680 R0(i,k_tgt) = (R0(i,k_tgt)*h_tgt_old + R0(i,k_src)*h_move) * I_hnew
2369 endif
2370
23710 T(i,k_tgt) = (T(i,k_tgt)*h_tgt_old + T(i,k_src)*h_move) * I_hnew
23720 S(i,k_tgt) = (S(i,k_tgt)*h_tgt_old + S(i,k_src)*h_move) * I_hnew
23730 Rcv(i,k_tgt) = (Rcv(i,k_tgt)*h_tgt_old + Rcv(i,k_src)*h_move) * I_hnew
2374
23750 d_eb(i,k_src) = d_eb(i,k_src) - h_move
23760 d_eb(i,k_tgt) = d_eb(i,k_tgt) + h_move
2377
2378 ! Remove the newly missing layer from the sorted list.
23790 do ks=ks_min+1,nks ; ks2(ks) = ks2(ks+1) ; enddo
23800 nks = nks-1
2381 enddo
2382
2383 ! Check again whether the layers are sorted, and go on to the next column
2384 ! if they are.
23850 sorted = .true.
23860 do ks=1,nks-1 ; if (ks2(ks) > ks2(ks+1)) sorted = .false. ; enddo
23870 if (sorted) cycle
2388
23890 if (nks > 1) then
2390 ! At this point, actually swap the properties of the layers, and place
2391 ! the remaining layers in order starting with nkmb.
2392
2393 ! Save all the properties of the nkmb layers that might be replaced.
23940 do k=1,nkmb
23950 h_tmp(k) = h(i,k)
23960 if (CS%nonBous_energetics) then
23970 SpV0_tmp(k) = SpV0(i,k)
2398 else
23990 R0_tmp(k) = R0(i,k)
2400 endif
24010 T_tmp(k) = T(i,k) ; S_tmp(k) = S(i,k) ; Rcv_tmp(k) = Rcv(i,k)
2402
24030 h(i,k) = 0.0
2404 enddo
2405
24060 do ks=nks,1,-1
24070 k_tgt = nkmb - nks + ks ; k_src = ks2(ks)
24080 if (k_tgt == k_src) then
24090 h(i,k_tgt) = h_tmp(k_tgt) ! This layer doesn't move, so put the water back.
24100 cycle
2411 endif
2412
2413 ! Note below that eps=0 for k<=nkmb.
24140 if (k_src > nkmb) then
24150 h_move = h(i,k_src)-eps(i,k_src)
24160 h(i,k_src) = eps(i,k_src)
24170 h(i,k_tgt) = h_move
24180 if (CS%nonBous_energetics) then
24190 SpV0(i,k_tgt) = SpV0(i,k_src)
2420 else
24210 R0(i,k_tgt) = R0(i,k_src)
2422 endif
2423
24240 T(i,k_tgt) = T(i,k_src) ; S(i,k_tgt) = S(i,k_src)
24250 Rcv(i,k_tgt) = Rcv(i,k_src)
2426
24270 d_eb(i,k_src) = d_eb(i,k_src) - h_move
24280 d_eb(i,k_tgt) = d_eb(i,k_tgt) + h_move
2429 else
24300 h(i,k_tgt) = h_tmp(k_src)
24310 if (CS%nonBous_energetics) then
24320 SpV0(i,k_tgt) = SpV0_tmp(k_src)
2433 else
24340 R0(i,k_tgt) = R0_tmp(k_src)
2435 endif
2436
24370 T(i,k_tgt) = T_tmp(k_src) ; S(i,k_tgt) = S_tmp(k_src)
24380 Rcv(i,k_tgt) = Rcv_tmp(k_src)
2439
24400 if (k_src > k_tgt) then
24410 d_eb(i,k_src) = d_eb(i,k_src) - h_tmp(k_src)
24420 d_eb(i,k_tgt) = d_eb(i,k_tgt) + h_tmp(k_src)
2443 else
24440 d_ea(i,k_src) = d_ea(i,k_src) - h_tmp(k_src)
24450 d_ea(i,k_tgt) = d_ea(i,k_tgt) + h_tmp(k_src)
2446 endif
2447 endif
2448 enddo
2449 endif
2450
2451 endif ; enddo
2452
24530end subroutine resort_ML
2454
2455!> This subroutine moves any water left in the former mixed layers into the
2456!! two buffer layers and may also move buffer layer water into the interior
2457!! isopycnal layers.
2458180subroutine mixedlayer_detrain_2(h, T, S, R0, Spv0, Rcv, RcvTgt, dt, dt_diag, d_ea, j, G, GV, US, CS, &
2459180 dR0_dT, dR0_dS, dSpV0_dT, dSpV0_dS, dRcv_dT, dRcv_dS, max_BL_det)
2460 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
2461 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
2462 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2].
2463 !! Layer 0 is the new mixed layer.
2464 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Potential temperature [C ~> degC].
2465 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Salinity [S ~> ppt].
2466 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: R0 !< Potential density referenced to
2467 !! surface pressure [R ~> kg m-3].
2468 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: SpV0 !< Specific volume referenced to
2469 !! surface pressure [R-1 ~> m3 kg-1]
2470 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: Rcv !< The coordinate defining potential
2471 !! density [R ~> kg m-3].
2472 real, dimension(SZK_(GV)), intent(in) :: RcvTgt !< The target value of Rcv for each
2473 !! layer [R ~> kg m-3].
2474 real, intent(in) :: dt !< Time increment [T ~> s].
2475 real, intent(in) :: dt_diag !< The diagnostic time step [T ~> s].
2476 real, dimension(SZI_(G),SZK_(GV)), intent(inout) :: d_ea !< The upward increase across a layer in
2477 !! the entrainment from above
2478 !! [H ~> m or kg m-2]. Positive d_ea
2479 !! goes with layer thickness increases.
2480 integer, intent(in) :: j !< The meridional row to work on.
2481 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
2482 type(bulkmixedlayer_CS), intent(inout) :: CS !< Bulk mixed layer control structure
2483 real, dimension(SZI_(G)), intent(in) :: dR0_dT !< The partial derivative of
2484 !! potential density referenced to the
2485 !! surface with potential temperature,
2486 !! [R C-1 ~> kg m-3 degC-1].
2487 real, dimension(SZI_(G)), intent(in) :: dR0_dS !< The partial derivative of
2488 !! potential density referenced to the
2489 !! surface with salinity
2490 !! [R S-1 ~> kg m-3 ppt-1].
2491 real, dimension(SZI_(G)), intent(in) :: dSpV0_dT !< The partial derivative of specific
2492 !! volume with respect to temeprature
2493 !! [R-1 C-1 ~> m3 kg-1 degC-1]
2494 real, dimension(SZI_(G)), intent(in) :: dSpV0_dS !< The partial derivative of specific
2495 !! volume with respect to salinity
2496 !! [R-1 S-1 ~> m3 kg-1 ppt-1]
2497 real, dimension(SZI_(G)), intent(in) :: dRcv_dT !< The partial derivative of
2498 !! coordinate defining potential density
2499 !! with potential temperature,
2500 !! [R C-1 ~> kg m-3 degC-1].
2501 real, dimension(SZI_(G)), intent(in) :: dRcv_dS !< The partial derivative of
2502 !! coordinate defining potential density
2503 !! with salinity [R S-1 ~> kg m-3 ppt-1].
2504 real, dimension(SZI_(G)), intent(in) :: max_BL_det !< If non-negative, the maximum
2505 !! detrainment permitted from the buffer
2506 !! layers [H ~> m or kg m-2].
2507
2508! This subroutine moves any water left in the former mixed layers into the
2509! two buffer layers and may also move buffer layer water into the interior
2510! isopycnal layers.
2511
2512 ! Local variables
2513 real :: h_to_bl ! The total thickness detrained to the buffer
2514 ! layers [H ~> m or kg m-2].
2515 real :: R0_to_bl ! The depth integrated amount of R0 that is detrained to the
2516 ! buffer layer [H R ~> kg m-2 or kg2 m-5]
2517 real :: SpV0_to_bl ! The depth integrated amount of SpV0 that is detrained to the
2518 ! buffer layer [H R-1 ~> m4 kg-1 or m]
2519 real :: Rcv_to_bl ! The depth integrated amount of Rcv that is detrained to the
2520 ! buffer layer [H R ~> kg m-2 or kg2 m-5]
2521 real :: T_to_bl ! The depth integrated amount of T that is detrained to the
2522 ! buffer layer [C H ~> degC m or degC kg m-2]
2523 real :: S_to_bl ! The depth integrated amount of S that is detrained to the
2524 ! buffer layer [S H ~> ppt m or ppt kg m-2]
2525 real :: h_min_bl ! The minimum buffer layer thickness [H ~> m or kg m-2].
2526
2527 real :: h1, h2 ! Scalar variables holding the values of
2528 ! h(i,CS%nkml+1) and h(i,CS%nkml+2) [H ~> m or kg m-2].
2529 real :: h1_avail ! The thickness of the upper buffer layer
2530 ! available to move into the lower buffer
2531 ! layer [H ~> m or kg m-2].
2532 real :: stays ! stays is the thickness of the upper buffer
2533 ! layer that remains there [H ~> m or kg m-2].
2534 real :: stays_min, stays_max ! The minimum and maximum permitted values of
2535 ! stays [H ~> m or kg m-2].
2536
2537 logical :: intermediate ! True if the water in layer kb1 is intermediate in density
2538 ! between the water in kb2 and the water being detrained.
2539 logical :: mergeable_bl ! If true, it is an option to combine the two
2540 ! buffer layers and create water that matches
2541 ! the target density of an interior layer.
2542 logical :: better_to_merge ! True if it is energetically favorable to merge layers
2543 real :: stays_merge ! If the two buffer layers can be combined
2544 ! stays_merge is the thickness of the upper
2545 ! layer that remains [H ~> m or kg m-2].
2546 real :: stays_min_merge ! The minimum allowed value of stays_merge [H ~> m or kg m-2].
2547
2548 real :: dR0_2dz, dRcv_2dz ! Half the vertical gradients of R0 and Rcv [R H-1 ~> kg m-4 or m-1]
2549 real :: dSpV0_2dz ! Half the vertical gradients of SpV0 and Rcv [R-1 H-1 ~> m2 kg-1 or m5 kg-2]
2550! real :: dT_2dz ! Half the vertical gradient of T [C H-1 ~> degC m-1 or degC m2 kg-1]
2551! real :: dS_2dz ! Half the vertical gradient of S [S H-1 ~> ppt m-1 or ppt m2 kg-1]
2552 real :: scale_slope ! A nondimensional number < 1 used to scale down
2553 ! the slope within the upper buffer layer when
2554 ! water MUST be detrained to the lower layer [nondim].
2555
2556 real :: dPE_extrap_rhoG ! The potential energy change due to dispersive
2557 ! advection or mixing layers, divided by
2558 ! rho_0*g [H2 ~> m2 or kg2 m-4].
2559 real :: dPE_extrapolate ! The potential energy change due to dispersive advection or
2560 ! mixing layers [R Z3 T-2 ~> J m-2].
2561 real :: dPE_det, dPE_merge ! The energy required to mix the detrained water
2562 ! into the buffer layer or the merge the two
2563 ! buffer layers [R H2 Z T-2 ~> J m-2 or J kg2 m-8].
2564 real :: dPE_det_nB, dPE_merge_nB ! The energy required to mix the detrained water
2565 ! into the buffer layer or the merge the two
2566 ! buffer layers [R Z3 T-2 ~> J m-2].
2567
2568 real :: h_from_ml ! The amount of additional water that must be
2569 ! drawn from the mixed layer [H ~> m or kg m-2].
2570 real :: h_det_h2 ! The amount of detrained water and mixed layer
2571 ! water that will go directly into the lower
2572 ! buffer layer [H ~> m or kg m-2].
2573
2574 real :: h_det_to_h2, h_ml_to_h2 ! The fluxes of detrained and mixed layer water to
2575 ! the lower buffer layer [H ~> m or kg m-2].
2576 real :: h_det_to_h1, h_ml_to_h1 ! The fluxes of detrained and mixed layer water to
2577 ! the upper buffer layer [H ~> m or kg m-2].
2578 real :: h1_to_h2, h1_to_k0 ! The fluxes of upper buffer layer water to the lower buffer layer
2579 ! and to an interior layer that is just denser than the lower
2580 ! buffer layer [H ~> m or kg m-2].
2581 real :: h2_to_k1, h2_to_k1_rem ! Fluxes of lower buffer layer water to the interior layer that
2582 ! is just denser than the lower buffer layer [H ~> m or kg m-2].
2583
2584 real :: R0_det ! Detrained value of potential density referenced to the surface [R ~> kg m-3]
2585 real :: SpV0_det ! Detrained value of specific volume referenced to the surface [R-1 ~> m3 kg-1]
2586 real :: T_det, S_det ! Detrained values of temperature [C ~> degC] and salinity [S ~> ppt]
2587 real :: Rcv_stays, R0_stays ! Values of Rcv and R0 that stay in a layer [R ~> kg m-3]
2588 real :: SpV0_stays ! Values of SpV0 that stay in a layer [R-1 ~> m3 kg-1]
2589 real :: T_stays, S_stays ! Values of T and S that stay in a layer, [C ~> degC] and S [S ~> ppt]
2590 real :: dSpice_det, dSpice_stays! The spiciness difference between an original
2591 ! buffer layer and the water that moves into
2592 ! an interior layer or that stays in that
2593 ! layer [R ~> kg m-3].
2594 real :: dSpice_lim, dSpice_lim2 ! Limits to the spiciness difference between
2595 ! the lower buffer layer and the water that
2596 ! moves into an interior layer [R ~> kg m-3].
2597 real :: dSpice_2dz ! The vertical gradient of spiciness used for
2598 ! advection [R H-1 ~> kg m-4 or m-1].
2599 real :: dSpiceSpV_stays ! The specific volume based spiciness difference between an original
2600 ! buffer layer and the water that stays in that layer [R-1 ~> m3 kg-1]
2601 real :: dSpiceSpV_lim ! A limit on the specific volume based spiciness difference
2602 ! between the lower buffer layer and the water that
2603 ! moves into an interior layer [R-1 ~> m3 kg-1]
2604 real :: dPE_ratio ! Multiplier of dPE_det at which merging is
2605 ! permitted - here (detrainment_per_day/dt)*30
2606 ! days? [nondim]
2607 real :: num_events ! The number of detrainment events over which
2608 ! to prefer merging the buffer layers [nondim].
2609 real :: dPE_time_ratio ! Larger of 1 and the detrainment timescale over dt [nondim].
2610 real :: dT_dS_gauge, dS_dT_gauge ! The relative scales of temperature and
2611 ! salinity changes in defining spiciness, in
2612 ! [C S-1 ~> degC ppt-1] and [S C-1 ~> ppt degC-1].
2613 real :: I_denom ! A work variable with units of [S2 R-2 ~> ppt2 m6 kg-2] or [R2 S2 ~> ppt2 kg2 m-6].
2614
2615 real :: g_2 ! 1/2 g_Earth [Z T-2 ~> m s-2].
2616 real :: Rho0xG ! Rho0 times G_Earth [R Z T-2 ~> kg m-2 s-2].
2617 real :: I2Rho0 ! 1 / (2 Rho0) [R-1 ~> m3 kg-1].
2618 real :: Idt_diag ! The inverse of the timestep used for diagnostics [T-1 ~> s-1].
2619 real :: Idt_H2 ! The square of the conversion from thickness to Z
2620 ! divided by the time step [Z2 H-2 T-1 ~> s-1 or m6 kg-2 s-1].
2621 logical :: stable_Rcv ! If true, the buffer layers are stable with
2622 ! respect to the coordinate potential density.
2623 real :: h_neglect ! A thickness that is so small it is usually lost
2624 ! in roundoff and can be neglected [H ~> m or kg m-2].
2625
2626 real :: s1en ! A work variable [R Z3 T-3 ~> W m-2]
2627 real :: s1, s2, bh0 ! Work variables [H ~> m or kg m-2].
2628 real :: s3sq ! A work variable [H2 ~> m2 or kg2 m-4].
2629 real :: I_ya, b1 ! Nondimensional work variables [nondim]
2630 real :: Ih, Ihdet, Ih1f, Ih2f ! Assorted inverse thickness work variables [H-1 ~> m-1 or m2 kg-1]
2631 real :: Ihk0, Ihk1, Ih12 ! Assorted inverse thickness work variables [H-1 ~> m-1 or m2 kg-1]
2632 real :: dR1, dR2, dR2b, dRk1 ! Assorted density difference work variables [R ~> kg m-3]
2633 real :: dR0, dR21, dRcv ! Assorted density difference work variables [R ~> kg m-3]
2634 real :: dSpV0, dSpVk1 ! Assorted specific volume difference work variables [R-1 ~> m3 kg-1]
2635 real :: dRcv_stays, dRcv_det, dRcv_lim ! Assorted densities [R ~> kg m-3]
2636 real :: Angstrom ! The minimum layer thickness [H ~> m or kg m-2].
2637
2638 real :: h2_to_k1_lim ! A limit on the thickness that can be detrained to layer k1 [H ~> m or kg m-2]
2639 real :: T_new, T_max, T_min ! Temperature of the detrained water and limits on it [C ~> degC]
2640 real :: S_new, S_max, S_min ! Salinity of the detrained water and limits on it [S ~> ppt]
2641 logical :: stable
2642 integer :: i, k, k0, k1, is, ie, nz, kb1, kb2, nkmb
2643
2644180 is = G%isc ; ie = G%iec ; nz = GV%ke
2645180 kb1 = CS%nkml+1 ; kb2 = CS%nkml+2
2646180 nkmb = CS%nkml+CS%nkbl
2647180 h_neglect = GV%H_subroundoff
2648180 g_2 = 0.5 * GV%g_Earth_Z_T2
2649180 Rho0xG = GV%Rho0 * GV%g_Earth_Z_T2
2650180 Idt_diag = 1.0 / dt_diag
2651180 Idt_H2 = GV%H_to_Z**2 / dt_diag
2652180 I2Rho0 = 0.5 / GV%Rho0
2653180 Angstrom = GV%Angstrom_H
2654
2655 ! This is hard coding of arbitrary and dimensional numbers.
2656180 dT_dS_gauge = CS%dT_dS_wt ; dS_dT_gauge = 1.0 / dT_dS_gauge
2657180 num_events = 10.0
2658
2659180 if (CS%nkbl /= 2) call MOM_error(FATAL, "MOM_mixed_layer: "// &
26600 "CS%nkbl must be 2 in mixedlayer_detrain_2.")
2661
2662180 if (dt < CS%BL_detrain_time) then ; dPE_time_ratio = CS%BL_detrain_time / (dt)
26630 else ; dPE_time_ratio = 1.0 ; endif
2664
266564980 do i=is,ie
2666
2667 ! Determine all of the properties being detrained from the mixed layer.
2668
2669 ! As coded this has the k and i loop orders switched, but k is CS%nkml is
2670 ! often just 1 or 2, so this seems like it should not be a problem, especially
2671 ! since it means that a number of variables can now be scalars, not arrays.
267264800 h_to_bl = 0.0 ; R0_to_bl = 0.0 ; SpV0_to_bl = 0.0
267364800 Rcv_to_bl = 0.0 ; T_to_bl = 0.0 ; S_to_bl = 0.0
2674
2675194400 do k=1,CS%nkml ; if (h(i,k) > 0.0) then
267679785 h_to_bl = h_to_bl + h(i,k)
267779785 if (CS%nonBous_energetics) then
26780 SpV0_to_bl = SpV0_to_bl + SpV0(i,k)*h(i,k)
2679 else
268079785 R0_to_bl = R0_to_bl + R0(i,k)*h(i,k)
2681 endif
2682
268379785 Rcv_to_bl = Rcv_to_bl + Rcv(i,k)*h(i,k)
268479785 T_to_bl = T_to_bl + T(i,k)*h(i,k)
268579785 S_to_bl = S_to_bl + S(i,k)*h(i,k)
2686
268779785 d_ea(i,k) = d_ea(i,k) - h(i,k)
268879785 h(i,k) = 0.0
2689 endif ; enddo
2690
269164800 if (CS%nonBous_energetics) then
26920 if (h_to_bl > 0.0) then ; SpV0_det = SpV0_to_bl / h_to_bl
26930 else ; SpV0_det = SpV0(i,0) ; endif
2694 else
269564800 if (h_to_bl > 0.0) then ; R0_det = R0_to_bl / h_to_bl
269623272 else ; R0_det = R0(i,0) ; endif
2697 endif
2698
2699 ! This code does both downward detrainment from both the mixed layer and the
2700 ! buffer layers.
2701 ! Several considerations apply in detraining water into the interior:
2702 ! (1) Water only moves into the interior from the deeper buffer layer,
2703 ! so the deeper buffer layer must have some mass.
2704 ! (2) The upper buffer layer must have some mass so the extrapolation of
2705 ! density is meaningful (i.e. there is not detrainment from the buffer
2706 ! layers when there is strong mixed layer entrainment).
2707 ! (3) The lower buffer layer density extrapolated to its base with a
2708 ! linear fit between the two layers must exceed the density of the
2709 ! next denser interior layer.
2710 ! (4) The average extrapolated coordinate density that is moved into the
2711 ! isopycnal interior matches the target value for that layer.
2712 ! (5) The potential energy change is calculated and might be used later
2713 ! to allow the upper buffer layer to mix more into the lower buffer
2714 ! layer.
2715
2716 ! Determine whether more must be detrained from the mixed layer to keep a
2717 ! minimal amount of mass in the buffer layers. In this case the 5% of the
2718 ! mixed layer thickness is hard-coded, but probably shouldn't be!
271964800 h_min_bl = MIN(CS%Hbuffer_min, CS%Hbuffer_rel_min*h(i,0))
2720
272164800 stable_Rcv = .true.
272264800 if (CS%nonBous_energetics) then
27230 if (((SpV0(i,kb1)-SpV0(i,kb2)) * (Rcv(i,kb2)-Rcv(i,kb1)) <= 0.0)) stable_Rcv = .false.
2724 else
272564800 if (((R0(i,kb2)-R0(i,kb1)) * (Rcv(i,kb2)-Rcv(i,kb1)) <= 0.0)) stable_Rcv = .false.
2726 endif
2727
272864800 h1 = h(i,kb1) ; h2 = h(i,kb2)
2729
273064800 h2_to_k1_rem = (h1 + h2) + h_to_bl
273164800 if ((max_BL_det(i) >= 0.0) .and. (h2_to_k1_rem > max_BL_det(i))) &
2732911 h2_to_k1_rem = max_BL_det(i)
2733
2734
273564800 if ((h2 == 0.0) .and. (h1 > 0.0)) then
2736 ! The lower buffer layer has been eliminated either by convective
2737 ! adjustment or entrainment from the interior, and its current properties
2738 ! are not meaningful, but may later be used to determine the properties of
2739 ! waters moving into the lower buffer layer. So the properties of the
2740 ! lower buffer layer are set to be between those of the upper buffer layer
2741 ! and the next denser interior layer, measured by R0 or SpV0. This probably does
2742 ! not happen very often, so I am not too worried about the inefficiency of
2743 ! the following loop.
27441373 do k1=kb2+1,nz ; if (h(i,k1) > 2.0*Angstrom) exit ; enddo
2745
2746246 Rcv(i,kb2) = Rcv(i,kb1) ; T(i,kb2) = T(i,kb1) ; S(i,kb2) = S(i,kb1)
2747
2748246 if (CS%nonBous_energetics) then
27490 SpV0(i,kb2) = SpV0(i,kb1)
27500 if (k1 <= nz) then ; if (SpV0(i,k1) <= SpV0(i,kb1)) then
27510 SpV0(i,kb2) = 0.5*(SpV0(i,kb1)+SpV0(i,k1))
2752
27530 Rcv(i,kb2) = 0.5*(Rcv(i,kb1)+Rcv(i,k1))
27540 T(i,kb2) = 0.5*(T(i,kb1)+T(i,k1))
27550 S(i,kb2) = 0.5*(S(i,kb1)+S(i,k1))
2756 endif ; endif
2757 else
2758246 R0(i,kb2) = R0(i,kb1)
2759
2760246 if (k1 <= nz) then ; if (R0(i,k1) >= R0(i,kb1)) then
2761246 R0(i,kb2) = 0.5*(R0(i,kb1)+R0(i,k1))
2762
2763246 Rcv(i,kb2) = 0.5*(Rcv(i,kb1)+Rcv(i,k1))
2764246 T(i,kb2) = 0.5*(T(i,kb1)+T(i,k1))
2765246 S(i,kb2) = 0.5*(S(i,kb1)+S(i,k1))
2766 endif ; endif
2767 endif
2768 endif ! (h2 = 0 && h1 > 0)
2769
277064800 dPE_extrap_rhoG = 0.0 ; dPE_extrapolate = 0.0 ; dPE_merge = 0.0 ; dPE_merge_nB = 0.0
277164800 mergeable_bl = .false.
277264800 if ((h1 > 0.0) .and. (h2 > 0.0) .and. (h_to_bl > 0.0) .and. &
2773 (stable_Rcv)) then
2774 ! Check whether it is permissible for the buffer layers to detrain
2775 ! into the interior isopycnal layers.
2776
2777 ! Determine the layer that has the lightest target density that is
2778 ! denser than the lowermost buffer layer.
2779364574 do k1=kb2+1,nz ; if (RcvTgt(k1) >= Rcv(i,kb2)) exit ; enddo ; k0 = k1-1
278037582 dR1 = RcvTgt(k0)-Rcv(i,kb1) ; dR2 = Rcv(i,kb2)-RcvTgt(k0)
2781
2782 ! Use an energy-balanced combination of downwind advection into the next
2783 ! denser interior layer and upwind advection from the upper buffer layer
2784 ! into the lower one, each with an energy change that equals that required
2785 ! to mix the detrained water with the upper buffer layer.
278637582 h1_avail = h1 - MAX(0.0,h_min_bl-h_to_bl)
278737582 if (CS%nonBous_energetics) then
27880 intermediate = (SpV0(i,kb1) > SpV0(i,kb2)) .and. (h_to_bl*SpV0(i,kb1) < SpV0_to_bl)
2789 else
279037582 intermediate = (R0(i,kb1) < R0(i,kb2)) .and. (h_to_bl*R0(i,kb1) > R0_to_bl)
2791 endif
2792
279337582 if ((k1<=nz) .and. (h2 > h_min_bl) .and. (h1_avail > 0.0) .and. intermediate) then
27942 if (CS%nonBous_energetics) then
2795 dSpVk1 = (RcvTgt(k1) - Rcv(i,kb2)) * (SpV0(i,kb2) - SpV0(i,kb1)) / &
27960 (Rcv(i,kb2) - Rcv(i,kb1))
27970 b1 = (RcvTgt(k1) - Rcv(i,kb2)) / (Rcv(i,kb2) - Rcv(i,kb1))
2798 else
2799 dRk1 = (RcvTgt(k1) - Rcv(i,kb2)) * (R0(i,kb2) - R0(i,kb1)) / &
28002 (Rcv(i,kb2) - Rcv(i,kb1))
28012 b1 = dRk1 / (R0(i,kb2) - R0(i,kb1))
2802 ! b1 = RcvTgt(k1) - Rcv(i,kb2)) / (Rcv(i,kb2) - Rcv(i,kb1))
2803 endif
2804
2805 ! Apply several limits to the detrainment.
2806 ! Entrain less than the mass in h2, and keep the base of the buffer
2807 ! layers from becoming shallower than any neighbors.
28082 h2_to_k1 = min(h2 - h_min_bl, h2_to_k1_rem)
2809 ! Balance downwind advection of density into the layer below the
2810 ! buffer layers with upwind advection from the layer above.
28112 if (h2_to_k1*(h1_avail + b1*(h1_avail + h2)) > h2*h1_avail) &
28122 h2_to_k1 = (h2*h1_avail) / (h1_avail + b1*(h1_avail + h2))
2813
28142 if (CS%nonBous_energetics) then
28150 if (h2_to_k1*(dSpVk1 * h2) < (h_to_bl*SpV0(i,kb1) - SpV0_to_bl) * h1) &
28160 h2_to_k1 = (h_to_bl*SpV0(i,kb1) - SpV0_to_bl) * h1 / (dSpVk1 * h2)
2817 else
28182 if (h2_to_k1*(dRk1 * h2) > (h_to_bl*R0(i,kb1) - R0_to_bl) * h1) &
28190 h2_to_k1 = (h_to_bl*R0(i,kb1) - R0_to_bl) * h1 / (dRk1 * h2)
2820 endif
2821
28222 if ((k1==kb2+1) .and. (CS%BL_extrap_lim > 0.)) then
2823 ! Simply do not detrain very light water into the lightest isopycnal
2824 ! coordinate layers if the density jump is too large.
28250 dRcv_lim = Rcv(i,kb2)-Rcv(i,0)
28260 do k=1,kb2 ; dRcv_lim = max(dRcv_lim, Rcv(i,kb2)-Rcv(i,k)) ; enddo
28270 dRcv_lim = CS%BL_extrap_lim*dRcv_lim
28280 if ((RcvTgt(k1) - Rcv(i,kb2)) >= dRcv_lim) then
28290 h2_to_k1 = 0.0
28300 elseif ((RcvTgt(k1) - Rcv(i,kb2)) > 0.5*dRcv_lim) then
28310 h2_to_k1 = h2_to_k1 * (2.0 - 2.0*((RcvTgt(k1) - Rcv(i,kb2)) / dRcv_lim))
2832 endif
2833 endif
2834
28352 dRcv = (RcvTgt(k1) - Rcv(i,kb2))
2836
2837 ! Use 2nd order upwind advection of spiciness, limited by the values
2838 ! in deeper thick layers to determine the detrained temperature and
2839 ! salinity.
2840 dSpice_det = (dS_dT_gauge*dRcv_dS(i)*(T(i,kb2)-T(i,kb1)) - &
2841 dT_dS_gauge*dRcv_dT(i)*(S(i,kb2)-S(i,kb1))) * &
28422 (h2 - h2_to_k1) / (h1 + h2)
28432 dSpice_lim = 0.0
28442 if (h(i,k1) > 10.0*Angstrom) then
2845 dSpice_lim = dS_dT_gauge*dRcv_dS(i)*(T(i,k1)-T(i,kb2)) - &
28462 dT_dS_gauge*dRcv_dT(i)*(S(i,k1)-S(i,kb2))
28472 if (dSpice_det*dSpice_lim <= 0.0) dSpice_lim = 0.0
2848 endif
28492 if (k1<nz) then ; if (h(i,k1+1) > 10.0*Angstrom) then
2850 dSpice_lim2 = dS_dT_gauge*dRcv_dS(i)*(T(i,k1+1)-T(i,kb2)) - &
28510 dT_dS_gauge*dRcv_dT(i)*(S(i,k1+1)-S(i,kb2))
28520 if ((dSpice_det*dSpice_lim2 > 0.0) .and. &
28530 (abs(dSpice_lim2) > abs(dSpice_lim))) dSpice_lim = dSpice_lim2
2854 endif ; endif
28552 if (abs(dSpice_det) > abs(dSpice_lim)) dSpice_det = dSpice_lim
2856
28572 I_denom = 1.0 / (dRcv_dS(i)**2 + (dT_dS_gauge*dRcv_dT(i))**2)
2858 T_det = T(i,kb2) + dT_dS_gauge * I_denom * &
28592 (dT_dS_gauge * dRcv_dT(i) * dRcv + dRcv_dS(i) * dSpice_det)
2860 S_det = S(i,kb2) + I_denom * &
28612 (dRcv_dS(i) * dRcv - dT_dS_gauge * dRcv_dT(i) * dSpice_det)
2862
2863 ! The detrained values of R0 or SpV0 are based on changes in T and S.
28642 if (CS%nonBous_energetics) then
2865 SpV0_det = SpV0(i,kb2) + (T_det-T(i,kb2)) * dSpV0_dT(i) + &
28660 (S_det-S(i,kb2)) * dSpV0_dS(i)
2867 else
2868 R0_det = R0(i,kb2) + (T_det-T(i,kb2)) * dR0_dT(i) + &
28692 (S_det-S(i,kb2)) * dR0_dS(i)
2870 endif
2871
28722 if (CS%BL_extrap_lim >= 0.) then
2873 ! Only do this detrainment if the new layer's temperature and salinity
2874 ! are not too far outside of the range of previous values.
28750 if (h(i,k1) > 10.0*Angstrom) then
28760 T_min = min(T(i,kb1), T(i,kb2), T(i,k1)) - CS%Allowed_T_chg
28770 T_max = max(T(i,kb1), T(i,kb2), T(i,k1)) + CS%Allowed_T_chg
28780 S_min = min(S(i,kb1), S(i,kb2), S(i,k1)) - CS%Allowed_S_chg
28790 S_max = max(S(i,kb1), S(i,kb2), S(i,k1)) + CS%Allowed_S_chg
2880 else
28810 T_min = min(T(i,kb1), T(i,kb2)) - CS%Allowed_T_chg
28820 T_max = max(T(i,kb1), T(i,kb2)) + CS%Allowed_T_chg
28830 S_min = min(S(i,kb1), S(i,kb2)) - CS%Allowed_S_chg
28840 S_max = max(S(i,kb1), S(i,kb2)) + CS%Allowed_S_chg
2885 endif
28860 Ihk1 = 1.0 / (h(i,k1) + h2_to_k1)
28870 T_new = (h(i,k1)*T(i,k1) + h2_to_k1*T_det) * Ihk1
28880 S_new = (h(i,k1)*S(i,k1) + h2_to_k1*S_det) * Ihk1
2889 ! A less restrictive limit might be used here.
2890 if ((T_new < T_min) .or. (T_new > T_max) .or. &
28910 (S_new < S_min) .or. (S_new > S_max)) &
28920 h2_to_k1 = 0.0
2893 endif
2894
28952 h1_to_h2 = b1*h2*h2_to_k1 / (h2 - (1.0+b1)*h2_to_k1)
2896
28972 Ihk1 = 1.0 / (h(i,k1) + h_neglect + h2_to_k1)
28982 Ih2f = 1.0 / ((h(i,kb2) - h2_to_k1) + h1_to_h2)
2899
2900 Rcv(i,kb2) = ((h(i,kb2)*Rcv(i,kb2) - h2_to_k1*RcvTgt(k1)) + &
29012 h1_to_h2*Rcv(i,kb1))*Ih2f
29022 Rcv(i,k1) = ((h(i,k1)+h_neglect)*Rcv(i,k1) + h2_to_k1*RcvTgt(k1)) * Ihk1
2903
2904 T(i,kb2) = ((h(i,kb2)*T(i,kb2) - h2_to_k1*T_det) + &
29052 h1_to_h2*T(i,kb1)) * Ih2f
29062 T(i,k1) = ((h(i,k1)+h_neglect)*T(i,k1) + h2_to_k1*T_det) * Ihk1
2907
2908 S(i,kb2) = ((h(i,kb2)*S(i,kb2) - h2_to_k1*S_det) + &
29092 h1_to_h2*S(i,kb1)) * Ih2f
29102 S(i,k1) = ((h(i,k1)+h_neglect)*S(i,k1) + h2_to_k1*S_det) * Ihk1
2911
2912 ! Changes in R0 or SpV0 are based on changes in T and S.
29132 if (CS%nonBous_energetics) then
29140 SpV0(i,kb2) = ((h(i,kb2)*SpV0(i,kb2) - h2_to_k1*SpV0_det) + h1_to_h2*SpV0(i,kb1)) * Ih2f
29150 SpV0(i,k1) = ((h(i,k1)+h_neglect)*SpV0(i,k1) + h2_to_k1*SpV0_det) * Ihk1
2916 else
29172 R0(i,kb2) = ((h(i,kb2)*R0(i,kb2) - h2_to_k1*R0_det) + h1_to_h2*R0(i,kb1)) * Ih2f
29182 R0(i,k1) = ((h(i,k1)+h_neglect)*R0(i,k1) + h2_to_k1*R0_det) * Ihk1
2919 endif
2920
29212 h(i,kb1) = h(i,kb1) - h1_to_h2 ; h1 = h(i,kb1)
29222 h(i,kb2) = (h(i,kb2) - h2_to_k1) + h1_to_h2 ; h2 = h(i,kb2)
29232 h(i,k1) = h(i,k1) + h2_to_k1
2924
29252 d_ea(i,kb1) = d_ea(i,kb1) - h1_to_h2
29262 d_ea(i,kb2) = (d_ea(i,kb2) - h2_to_k1) + h1_to_h2
29272 d_ea(i,k1) = d_ea(i,k1) + h2_to_k1
29282 h2_to_k1_rem = max(h2_to_k1_rem - h2_to_k1, 0.0)
2929
2930 ! The lower buffer layer has become lighter - it may be necessary to
2931 ! adjust k1 lighter.
29322 if ((k1>kb2+1) .and. (RcvTgt(k1-1) >= Rcv(i,kb2))) then
29330 do k1=k1,kb2+1,-1 ; if (RcvTgt(k1-1) < Rcv(i,kb2)) exit ; enddo
2934 endif
2935 endif
2936
293737582 k0 = k1-1
293837582 dR1 = RcvTgt(k0)-Rcv(i,kb1) ; dR2 = Rcv(i,kb2)-RcvTgt(k0)
2939
294037582 if (CS%nonBous_energetics) then
29410 stable = (SpV0(i,kb2) < SpV0(i,kb1))
2942 else
294337582 stable = (R0(i,kb2) > R0(i,kb1))
2944 endif
2945
294637582 if ((k0>kb2) .and. (dR1 > 0.0) .and. (h1 > h_min_bl) .and. (h2*dR2 < h1*dR1) .and. stable) then
2947 ! An interior isopycnal layer (k0) is intermediate in density between
2948 ! the two buffer layers, and there can be detrainment. The entire
2949 ! lower buffer layer is combined with a portion of the upper buffer
2950 ! layer to match the target density of layer k0.
2951 stays_merge = 2.0*(h1+h2)*(h1*dR1 - h2*dR2) / &
2952 ((dR1+dR2)*h1 + dR1*(h1+h2) + &
29530 sqrt((dR2*h1-dR1*h2)**2 + 4*(h1+h2)*h2*(dR1+dR2)*dR2))
2954
29550 if (CS%nonBous_energetics) then
2956 stays_min_merge = MAX(h_min_bl, 2.0*h_min_bl - h_to_bl, &
29570 h1 - (h1+h2)*(SpV0(i,kb1) - SpV0_det) / (SpV0(i,kb2) - SpV0(i,kb1)))
29580 if ((stays_merge > stays_min_merge) .and. (stays_merge + h2_to_k1_rem >= h1 + h2)) then
29590 mergeable_bl = .true.
29600 dPE_merge_nB = g_2*GV%H_to_RZ**2*(SpV0(i,kb1)-SpV0(i,kb2)) * ((h1-stays_merge)*(h2-stays_merge))
2961 endif
2962 else
2963 stays_min_merge = MAX(h_min_bl, 2.0*h_min_bl - h_to_bl, &
29640 h1 - (h1+h2)*(R0(i,kb1) - R0_det) / (R0(i,kb2) - R0(i,kb1)))
29650 if ((stays_merge > stays_min_merge) .and. (stays_merge + h2_to_k1_rem >= h1 + h2)) then
29660 mergeable_bl = .true.
29670 dPE_merge = g_2*(R0(i,kb2)-R0(i,kb1)) * (h1-stays_merge)*(h2-stays_merge)
2968 endif
2969 endif
2970 endif
2971
297237582 if ((k1<=nz).and.(.not.mergeable_bl)) then
2973 ! Check whether linear extrapolation of density (i.e. 2nd order upwind
2974 ! advection) will allow some of the lower buffer layer to detrain into
2975 ! the next denser interior layer (k1).
297637582 dR2b = RcvTgt(k1)-Rcv(i,kb2) ; dR21 = Rcv(i,kb2) - Rcv(i,kb1)
297737582 if (dR2b*(h1+h2) < h2*dR21) then
2978 ! Some of layer kb2 is denser than k1.
29790 h2_to_k1 = min(h2 - (h1+h2) * dR2b / dR21, h2_to_k1_rem)
2980
29810 if (h2 > h2_to_k1) then
29820 dRcv = (RcvTgt(k1) - Rcv(i,kb2))
2983
2984 ! Use 2nd order upwind advection of spiciness, limited by the values
2985 ! in deeper thick layers to determine the detrained temperature and
2986 ! salinity.
2987 dSpice_det = (dS_dT_gauge*dRcv_dS(i)*(T(i,kb2)-T(i,kb1)) - &
2988 dT_dS_gauge*dRcv_dT(i)*(S(i,kb2)-S(i,kb1))) * &
29890 (h2 - h2_to_k1) / (h1 + h2)
29900 dSpice_lim = 0.0
29910 if (h(i,k1) > 10.0*Angstrom) then
2992 dSpice_lim = dS_dT_gauge*dRcv_dS(i)*(T(i,k1)-T(i,kb2)) - &
29930 dT_dS_gauge*dRcv_dT(i)*(S(i,k1)-S(i,kb2))
29940 if (dSpice_det*dSpice_lim <= 0.0) dSpice_lim = 0.0
2995 endif
29960 if (k1<nz) then ; if (h(i,k1+1) > 10.0*Angstrom) then
2997 dSpice_lim2 = dS_dT_gauge*dRcv_dS(i)*(T(i,k1+1)-T(i,kb2)) - &
29980 dT_dS_gauge*dRcv_dT(i)*(S(i,k1+1)-S(i,kb2))
29990 if ((dSpice_det*dSpice_lim2 > 0.0) .and. &
30000 (abs(dSpice_lim2) > abs(dSpice_lim))) dSpice_lim = dSpice_lim2
3001 endif ; endif
30020 if (abs(dSpice_det) > abs(dSpice_lim)) dSpice_det = dSpice_lim
3003
30040 I_denom = 1.0 / (dRcv_dS(i)**2 + (dT_dS_gauge*dRcv_dT(i))**2)
3005 T_det = T(i,kb2) + dT_dS_gauge * I_denom * &
30060 (dT_dS_gauge * dRcv_dT(i) * dRcv + dRcv_dS(i) * dSpice_det)
3007 S_det = S(i,kb2) + I_denom * &
30080 (dRcv_dS(i) * dRcv - dT_dS_gauge * dRcv_dT(i) * dSpice_det)
3009 ! The detrained values of R0 or SpV0 are based on changes in T and S.
30100 if (CS%nonBous_energetics) then
3011 SpV0_det = SpV0(i,kb2) + (T_det-T(i,kb2)) * dSpV0_dT(i) + &
30120 (S_det-S(i,kb2)) * dSpV0_dS(i)
3013 else
3014 R0_det = R0(i,kb2) + (T_det-T(i,kb2)) * dR0_dT(i) + &
30150 (S_det-S(i,kb2)) * dR0_dS(i)
3016 endif
3017
3018 ! Now that the properties of the detrained water are known,
3019 ! potentially limit the amount of water that is detrained to
3020 ! avoid creating unphysical properties in the remaining water.
30210 Ih2f = 1.0 / (h2 - h2_to_k1)
3022
30230 T_min = min(T(i,kb2), T(i,kb1)) - CS%Allowed_T_chg
30240 T_max = max(T(i,kb2), T(i,kb1)) + CS%Allowed_T_chg
30250 T_new = (h2*T(i,kb2) - h2_to_k1*T_det)*Ih2f
30260 if (T_new < T_min) then
30270 h2_to_k1_lim = h2 * (T(i,kb2) - T_min) / (T_det - T_min)
3028! write(mesg,'("Low temperature limits det to ", &
3029! & 1pe12.5, " from ", 1pe12.5, " at ", 1pg11.4,"E, ",1pg11.4,"N. T=", &
3030! & 5(1pe12.5))') &
3031! h2_to_k1_lim, h2_to_k1, G%geoLonT(i,j), G%geoLatT(i,j), &
3032! T_new, T(i,kb2), T(i,kb1), T_det, T_new-T_min
3033! call MOM_error(WARNING, mesg)
30340 h2_to_k1 = h2_to_k1_lim
30350 Ih2f = 1.0 / (h2 - h2_to_k1)
30360 elseif (T_new > T_max) then
30370 h2_to_k1_lim = h2 * (T(i,kb2) - T_max) / (T_det - T_max)
3038! write(mesg,'("High temperature limits det to ", &
3039! & 1pe12.5, " from ", 1pe12.5, " at ", 1pg11.4,"E, ",1pg11.4,"N. T=", &
3040! & 5(1pe12.5))') &
3041! h2_to_k1_lim, h2_to_k1, G%geoLonT(i,j), G%geoLatT(i,j), &
3042! T_new, T(i,kb2), T(i,kb1), T_det, T_new-T_max
3043! call MOM_error(WARNING, mesg)
30440 h2_to_k1 = h2_to_k1_lim
30450 Ih2f = 1.0 / (h2 - h2_to_k1)
3046 endif
30470 S_min = max(min(S(i,kb2), S(i,kb1)) - CS%Allowed_S_chg, 0.0)
30480 S_max = max(S(i,kb2), S(i,kb1)) + CS%Allowed_S_chg
30490 S_new = (h2*S(i,kb2) - h2_to_k1*S_det)*Ih2f
30500 if (S_new < S_min) then
30510 h2_to_k1_lim = h2 * (S(i,kb2) - S_min) / (S_det - S_min)
3052! write(mesg,'("Low salinity limits det to ", &
3053! & 1pe12.5, " from ", 1pe12.5, " at ", 1pg11.4,"E, ",1pg11.4,"N. S=", &
3054! & 5(1pe12.5))') &
3055! h2_to_k1_lim, h2_to_k1, G%geoLonT(i,j), G%geoLatT(i,j), &
3056! S_new, S(i,kb2), S(i,kb1), S_det, S_new-S_min
3057! call MOM_error(WARNING, mesg)
30580 h2_to_k1 = h2_to_k1_lim
30590 Ih2f = 1.0 / (h2 - h2_to_k1)
30600 elseif (S_new > S_max) then
30610 h2_to_k1_lim = h2 * (S(i,kb2) - S_max) / (S_det - S_max)
3062! write(mesg,'("High salinity limits det to ", &
3063! & 1pe12.5, " from ", 1pe12.5, " at ", 1pg11.4,"E, ",1pg11.4,"N. S=", &
3064! & 5(1pe12.5))') &
3065! h2_to_k1_lim, h2_to_k1, G%geoLonT(i,j), G%geoLatT(i,j), &
3066! S_new, S(i,kb2), S(i,kb1), S_det, S_new-S_max
3067! call MOM_error(WARNING, mesg)
30680 h2_to_k1 = h2_to_k1_lim
30690 Ih2f = 1.0 / (h2 - h2_to_k1)
3070 endif
3071
30720 Ihk1 = 1.0 / (h(i,k1) + h_neglect + h2_to_k1)
30730 Rcv(i,k1) = ((h(i,k1)+h_neglect)*Rcv(i,k1) + h2_to_k1*RcvTgt(k1)) * Ihk1
30740 Rcv(i,kb2) = Rcv(i,kb2) - h2_to_k1*dRcv*Ih2f
3075
30760 T(i,kb2) = (h2*T(i,kb2) - h2_to_k1*T_det)*Ih2f
30770 T(i,k1) = ((h(i,k1)+h_neglect)*T(i,k1) + h2_to_k1*T_det) * Ihk1
3078
30790 S(i,kb2) = (h2*S(i,kb2) - h2_to_k1*S_det) * Ih2f
30800 S(i,k1) = ((h(i,k1)+h_neglect)*S(i,k1) + h2_to_k1*S_det) * Ihk1
3081
3082 ! Changes in R0 or SpV0 are based on changes in T and S.
30830 if (CS%nonBous_energetics) then
30840 SpV0(i,kb2) = (h2*SpV0(i,kb2) - h2_to_k1*SpV0_det) * Ih2f
30850 SpV0(i,k1) = ((h(i,k1)+h_neglect)*SpV0(i,k1) + h2_to_k1*SpV0_det) * Ihk1
3086 else
30870 R0(i,kb2) = (h2*R0(i,kb2) - h2_to_k1*R0_det) * Ih2f
30880 R0(i,k1) = ((h(i,k1)+h_neglect)*R0(i,k1) + h2_to_k1*R0_det) * Ihk1
3089 endif
3090 else
3091 ! h2==h2_to_k1 can happen if dR2b = 0 exactly, but this is very
3092 ! unlikely. In this case the entirety of layer kb2 is detrained.
30930 h2_to_k1 = h2 ! These 2 lines are probably unnecessary.
30940 Ihk1 = 1.0 / (h(i,k1) + h2)
3095
30960 Rcv(i,k1) = (h(i,k1)*Rcv(i,k1) + h2*Rcv(i,kb2)) * Ihk1
30970 T(i,k1) = (h(i,k1)*T(i,k1) + h2*T(i,kb2)) * Ihk1
30980 S(i,k1) = (h(i,k1)*S(i,k1) + h2*S(i,kb2)) * Ihk1
30990 if (CS%nonBous_energetics) then
31000 SpV0(i,k1) = (h(i,k1)*SpV0(i,k1) + h2*SpV0(i,kb2)) * Ihk1
3101 else
31020 R0(i,k1) = (h(i,k1)*R0(i,k1) + h2*R0(i,kb2)) * Ihk1
3103 endif
3104 endif
3105
31060 h(i,k1) = h(i,k1) + h2_to_k1
31070 h(i,kb2) = h(i,kb2) - h2_to_k1 ; h2 = h(i,kb2)
3108 ! dPE_extrap_rhoG should be positive here.
31090 if (CS%nonBous_energetics) then
31100 dPE_extrap_rhoG = 0.5*(SpV0(i,kb2)-SpV0_det) * (h2_to_k1*h2) / SpV0(i,k1)
31110 dPE_extrapolate = 0.5*GV%g_Earth_Z_T2*GV%H_to_RZ**2*(SpV0(i,kb2)-SpV0_det) * (h2_to_k1*h2)
3112 else
31130 dPE_extrap_rhoG = I2Rho0*(R0_det-R0(i,kb2))*h2_to_k1*h2
3114 endif
3115
31160 d_ea(i,kb2) = d_ea(i,kb2) - h2_to_k1
31170 d_ea(i,k1) = d_ea(i,k1) + h2_to_k1
31180 h2_to_k1_rem = max(h2_to_k1_rem - h2_to_k1, 0.0)
3119 endif
3120 endif ! Detrainment by extrapolation.
3121
3122 endif ! Detrainment to the interior at all.
3123
3124 ! Does some of the detrained water go into the lower buffer layer?
312564800 h_det_h2 = MAX(h_min_bl-(h1+h2), 0.0)
312664980 if (h_det_h2 > 0.0) then
3127 ! Detrained water will go into both upper and lower buffer layers.
3128 ! h(kb2) will be h_min_bl, but h(kb1) may be larger if there was already
3129 ! ample detrainment; all water in layer kb1 moves into layer kb2.
3130
3131 ! Determine the fluxes between the various layers.
313264798 h_det_to_h2 = MIN(h_to_bl, h_det_h2)
313364798 h_ml_to_h2 = h_det_h2 - h_det_to_h2
313464798 h_det_to_h1 = h_to_bl - h_det_to_h2
313564798 h_ml_to_h1 = MAX(h_min_bl-h_det_to_h1,0.0)
3136
313764798 Ih = 1.0/h_min_bl
313864798 Ihdet = 0.0 ; if (h_to_bl > 0.0) Ihdet = 1.0 / h_to_bl
313964798 Ih1f = 1.0 / (h_det_to_h1 + h_ml_to_h1)
3140
314164798 if (CS%nonBous_energetics) then
3142 SpV0(i,kb2) = ((h2*SpV0(i,kb2) + h1*SpV0(i,kb1)) + &
31430 (h_det_to_h2*SpV0_to_bl*Ihdet + h_ml_to_h2*SpV0(i,0))) * Ih
31440 SpV0(i,kb1) = (h_det_to_h1*SpV0_to_bl*Ihdet + h_ml_to_h1*SpV0(i,0)) * Ih1f
3145 else
3146 R0(i,kb2) = ((h2*R0(i,kb2) + h1*R0(i,kb1)) + &
314764798 (h_det_to_h2*R0_to_bl*Ihdet + h_ml_to_h2*R0(i,0))) * Ih
314864798 R0(i,kb1) = (h_det_to_h1*R0_to_bl*Ihdet + h_ml_to_h1*R0(i,0)) * Ih1f
3149 endif
3150
3151 Rcv(i,kb2) = ((h2*Rcv(i,kb2) + h1*Rcv(i,kb1)) + &
315264798 (h_det_to_h2*Rcv_to_bl*Ihdet + h_ml_to_h2*Rcv(i,0))) * Ih
315364798 Rcv(i,kb1) = (h_det_to_h1*Rcv_to_bl*Ihdet + h_ml_to_h1*Rcv(i,0)) * Ih1f
3154
3155 T(i,kb2) = ((h2*T(i,kb2) + h1*T(i,kb1)) + &
315664798 (h_det_to_h2*T_to_bl*Ihdet + h_ml_to_h2*T(i,0))) * Ih
315764798 T(i,kb1) = (h_det_to_h1*T_to_bl*Ihdet + h_ml_to_h1*T(i,0)) * Ih1f
3158
3159 S(i,kb2) = ((h2*S(i,kb2) + h1*S(i,kb1)) + &
316064798 (h_det_to_h2*S_to_bl*Ihdet + h_ml_to_h2*S(i,0))) * Ih
316164798 S(i,kb1) = (h_det_to_h1*S_to_bl*Ihdet + h_ml_to_h1*S(i,0)) * Ih1f
3162
3163 ! Recall that h1 = h(i,kb1) & h2 = h(i,kb2).
316464798 d_ea(i,1) = d_ea(i,1) - (h_ml_to_h1 + h_ml_to_h2)
316564798 d_ea(i,kb1) = d_ea(i,kb1) + ((h_det_to_h1 + h_ml_to_h1) - h1)
316664798 d_ea(i,kb2) = d_ea(i,kb2) + (h_min_bl - h2)
3167
316864798 h(i,kb1) = h_det_to_h1 + h_ml_to_h1 ; h(i,kb2) = h_min_bl
316964798 h(i,0) = h(i,0) - (h_ml_to_h1 + h_ml_to_h2)
3170
3171
317264798 if (allocated(CS%diag_PE_detrain) .or. allocated(CS%diag_PE_detrain2)) then
31730 if (CS%nonBous_energetics) then
31740 SpV0_det = SpV0_to_bl*Ihdet
3175 s1en = Idt_diag * ( -GV%H_to_RZ**2 * g_2 * ((SpV0(i,kb2)-SpV0(i,kb1))*h1*h2 + &
3176 h_det_to_h2*( (SpV0(i,kb1)-SpV0_det)*h1 + (SpV0(i,kb2)-SpV0_det)*h2 ) + &
3177 h_ml_to_h2*( (SpV0(i,kb2)-SpV0(i,0))*h2 + (SpV0(i,kb1)-SpV0(i,0))*h1 + &
3178 (SpV0_det-SpV0(i,0))*h_det_to_h2 ) + &
31790 h_det_to_h1*h_ml_to_h1*(SpV0_det-SpV0(i,0))) - dPE_extrapolate )
3180
31810 if (allocated(CS%diag_PE_detrain2)) &
31820 CS%diag_PE_detrain2(i,j) = CS%diag_PE_detrain2(i,j) + s1en + Idt_diag*dPE_extrapolate
3183 else
31840 R0_det = R0_to_bl*Ihdet
3185 s1en = g_2 * Idt_H2 * ( ((R0(i,kb2)-R0(i,kb1))*h1*h2 + &
3186 h_det_to_h2*( (R0(i,kb1)-R0_det)*h1 + (R0(i,kb2)-R0_det)*h2 ) + &
3187 h_ml_to_h2*( (R0(i,kb2)-R0(i,0))*h2 + (R0(i,kb1)-R0(i,0))*h1 + &
3188 (R0_det-R0(i,0))*h_det_to_h2 ) + &
31890 h_det_to_h1*h_ml_to_h1*(R0_det-R0(i,0))) - 2.0*GV%Rho0*dPE_extrap_rhoG )
3190
31910 if (allocated(CS%diag_PE_detrain2)) &
31920 CS%diag_PE_detrain2(i,j) = CS%diag_PE_detrain2(i,j) + s1en + Idt_H2*Rho0xG*dPE_extrap_rhoG
3193 endif
3194
31950 if (allocated(CS%diag_PE_detrain)) &
31960 CS%diag_PE_detrain(i,j) = CS%diag_PE_detrain(i,j) + s1en
3197 endif
3198
31992 elseif ((h_to_bl > 0.0) .or. (h1 < h_min_bl) .or. (h2 < h_min_bl)) then
3200 ! Determine how much of the upper buffer layer will be moved into
3201 ! the lower buffer layer and the properties with which it is moving.
3202 ! This implementation assumes a 2nd-order upwind advection of density
3203 ! from the uppermost buffer layer into the next one down.
32042 h_from_ml = h_min_bl + MAX(h_min_bl-h2,0.0) - h1 - h_to_bl
32052 if (h_from_ml > 0.0) then
3206 ! Some water needs to be moved from the mixed layer so that the upper
3207 ! (and perhaps lower) buffer layers exceed their minimum thicknesses.
32080 if (CS%nonBous_energetics) then
3209 ! The choice of which specific volume to use in the denominator could be revisited.
3210 ! dPE_extrap_rhoG = dPE_extrap_rhoG + 0.5*h_from_ml*(SpV0_to_bl - SpV0(i,0)*h_to_bl) / SpV0(i,0)
3211 dPE_extrap_rhoG = dPE_extrap_rhoG + 0.5*h_from_ml*(SpV0_to_bl - SpV0(i,0)*h_to_bl) * &
32120 ( (h_to_bl + h_from_ml) / (SpV0_to_bl + h_from_ml*SpV0(i,0)) )
3213 dPE_extrapolate = dPE_extrapolate + 0.5*GV%g_Earth_Z_T2*GV%H_to_RZ**2 * &
32140 h_from_ml*(SpV0_to_bl - SpV0(i,0)*h_to_bl)
32150 SpV0_to_bl = SpV0_to_bl + h_from_ml*SpV0(i,0)
3216 else
32170 dPE_extrap_rhoG = dPE_extrap_rhoG - I2Rho0*h_from_ml*(R0_to_bl - R0(i,0)*h_to_bl)
32180 R0_to_bl = R0_to_bl + h_from_ml*R0(i,0)
3219 endif
32200 Rcv_to_bl = Rcv_to_bl + h_from_ml*Rcv(i,0)
32210 T_to_bl = T_to_bl + h_from_ml*T(i,0)
32220 S_to_bl = S_to_bl + h_from_ml*S(i,0)
3223
32240 h_to_bl = h_to_bl + h_from_ml
32250 h(i,0) = h(i,0) - h_from_ml
32260 d_ea(i,1) = d_ea(i,1) - h_from_ml
3227 endif
3228
3229 ! The absolute value should be unnecessary and 1e9 is just a large number.
32302 b1 = 1.0e9
32312 if (CS%nonBous_energetics) then
32320 if (SpV0(i,kb1) - SpV0(i,kb2) > 1.0e-9*abs(SpV0_det - SpV0(i,kb1))) &
32330 b1 = abs(SpV0_det - SpV0(i,kb1)) / (SpV0(i,kb1) - SpV0(i,kb2))
3234 else
32352 if (R0(i,kb2) - R0(i,kb1) > 1.0e-9*abs(R0(i,kb1) - R0_det)) &
32362 b1 = abs(R0(i,kb1) - R0_det) / (R0(i,kb2) - R0(i,kb1))
3237 endif
32382 stays_min = MAX((1.0-b1)*h1 - b1*h2, 0.0, h_min_bl - h_to_bl)
32392 stays_max = h1 - MAX(h_min_bl-h2,0.0)
3240
32412 scale_slope = 1.0
32422 if (stays_max <= stays_min) then
32432 stays = stays_max
32442 mergeable_bl = .false.
32452 if (stays_max < h1) scale_slope = (h1 - stays_min) / (h1 - stays_max)
3246 else
3247 ! There are numerous temporary variables used here that should not be
3248 ! used outside of this "else" branch: s1, s2, s3sq, I_ya, bh0
32490 bh0 = b1*h_to_bl
32500 I_ya = (h1 + h2) / ((h1 + h2) + h_to_bl)
3251 ! s1 is the amount staying that minimizes the PE increase.
32520 s1 = 0.5*(h1 + (h2 - bh0) * I_ya) ; s2 = h1 - s1
3253
32540 if (s2 < 0.0) then
3255 ! The energy released by detrainment from the lower buffer layer can be
3256 ! used to mix water from the upper buffer layer into the lower one.
32570 s3sq = I_ya*MAX(bh0*h1-dPE_extrap_rhoG, 0.0)
3258 else
32590 s3sq = I_ya*(bh0*h1-MIN(dPE_extrap_rhoG,0.0))
3260 endif
3261
32620 if (s3sq == 0.0) then
3263 ! There is a simple, exact solution to the quadratic equation, namely:
32640 stays = h1 ! This will revert to stays_max later.
32650 elseif (s2*s2 <= s3sq) then
3266 ! There is no solution with 0 PE change - use the minimum energy input.
32670 stays = s1
3268 else
3269 ! The following choose the solutions that are continuous with all water
3270 ! staying in the upper buffer layer when there is no detrainment,
3271 ! namely the + root when s2>0 and the - root otherwise. They also
3272 ! carefully avoid differencing large numbers, using s2 = (h1-s).
32730 if (bh0 <= 0.0) then ; stays = h1
32740 elseif (s2 > 0.0) then
3275 ! stays = s + sqrt(s2*s2 - s3sq) ! Note that s2 = h1-s
32760 if (s1 >= stays_max) then ; stays = stays_max
32770 elseif (s1 >= 0.0) then ; stays = s1 + sqrt(s2*s2 - s3sq)
32780 else ; stays = (h1*(s2-s1) - s3sq) / (-s1 + sqrt(s2*s2 - s3sq))
3279 endif
3280 else
3281 ! stays = s - sqrt(s2*s2 - s3sq) ! Note that s2 = h1-s & stays_min >= 0
32820 if (s1 <= stays_min) then ; stays = stays_min
32830 else ; stays = (h1*(s1-s2) + s3sq) / (s1 + sqrt(s2*s2 - s3sq))
3284 endif
3285 endif
3286 endif
3287
3288 ! Limit the amount that stays so that the motion of water is from the
3289 ! upper buffer layer into the lower, but no more than is in the upper
3290 ! layer, and the water left in the upper layer is no lighter than the
3291 ! detrained water.
32920 if (stays >= stays_max) then ; stays = stays_max
32930 elseif (stays < stays_min) then ; stays = stays_min
3294 endif
3295 endif
3296
32972 if (CS%nonBous_energetics) then
3298 dPE_det_nB = -g_2*GV%H_to_RZ**2*((SpV0(i,kb1)*h_to_bl - SpV0_to_bl)*stays + &
3299 (SpV0(i,kb2)-SpV0(i,kb1)) * (h1-stays) * &
3300 (h2 - scale_slope*stays*((h1+h2)+h_to_bl)/(h1+h2)) ) - &
33010 dPE_extrapolate
3302 else
3303 dPE_det = g_2*((R0(i,kb1)*h_to_bl - R0_to_bl)*stays + &
3304 (R0(i,kb2)-R0(i,kb1)) * (h1-stays) * &
3305 (h2 - scale_slope*stays*((h1+h2)+h_to_bl)/(h1+h2)) ) - &
33062 Rho0xG*dPE_extrap_rhoG
3307 endif
3308
33092 if (dPE_time_ratio*h_to_bl > h_to_bl+h(i,0)) then
33102 dPE_ratio = (h_to_bl+h(i,0)) / h_to_bl
3311 else
33120 dPE_ratio = dPE_time_ratio
3313 endif
3314
33152 if (CS%nonBous_energetics) then
33160 better_to_merge = (num_events*dPE_ratio*dPE_det_nB > dPE_merge_nB)
3317 else
33182 better_to_merge = (num_events*dPE_ratio*dPE_det > dPE_merge)
3319 endif
3320
33212 if (mergeable_bl .and. better_to_merge) then
3322 ! It is energetically preferable to merge the two buffer layers, detrain
3323 ! them into interior layer (k0), move the remaining upper buffer layer
3324 ! water into the lower buffer layer, and detrain undiluted into the
3325 ! upper buffer layer.
33260 h1_to_k0 = (h1-stays_merge)
33270 stays = MAX(h_min_bl-h_to_bl,0.0)
33280 h1_to_h2 = stays_merge - stays
3329
33300 Ihk0 = 1.0 / ((h1_to_k0 + h2) + h(i,k0))
33310 Ih1f = 1.0 / (h_to_bl + stays) ; Ih2f = 1.0 / h1_to_h2
33320 Ih12 = 1.0 / (h1 + h2)
3333
33340 dRcv_2dz = (Rcv(i,kb1) - Rcv(i,kb2)) * Ih12
33350 dRcv_stays = dRcv_2dz*(h1_to_k0 + h1_to_h2)
33360 dRcv_det = - dRcv_2dz*(stays + h1_to_h2)
3337 Rcv(i,k0) = ((h1_to_k0*(Rcv(i,kb1) + dRcv_det) + &
33380 h2*Rcv(i,kb2)) + h(i,k0)*Rcv(i,k0)) * Ihk0
33390 Rcv(i,kb2) = Rcv(i,kb1) + dRcv_2dz*(h1_to_k0-stays)
33400 Rcv(i,kb1) = (Rcv_to_bl + stays*(Rcv(i,kb1) + dRcv_stays)) * Ih1f
3341
3342 ! Use 2nd order upwind advection of spiciness, limited by the value in
3343 ! the water from the mixed layer to determine the temperature and
3344 ! salinity of the water that stays in the buffer layers.
33450 I_denom = 1.0 / (dRcv_dS(i)**2 + (dT_dS_gauge*dRcv_dT(i))**2)
3346 dSpice_2dz = (dS_dT_gauge*dRcv_dS(i)*(T(i,kb1)-T(i,kb2)) - &
33470 dT_dS_gauge*dRcv_dT(i)*(S(i,kb1)-S(i,kb2))) * Ih12
33480 if (CS%nonBous_energetics) then
3349 ! Use the specific volume differences to limit the coordinate density change.
3350 dSpice_lim = -Rcv(i,kb1) * (dS_dT_gauge*dSpV0_dS(i)*(T_to_bl-T(i,kb1)*h_to_bl) - &
33510 dT_dS_gauge*dSpV0_dT(i)*(S_to_bl-S(i,kb1)*h_to_bl)) / (SpV0(i,kb1) * h_to_bl)
3352 else
3353 dSpice_lim = (dS_dT_gauge*dR0_dS(i)*(T_to_bl-T(i,kb1)*h_to_bl) - &
33540 dT_dS_gauge*dR0_dT(i)*(S_to_bl-S(i,kb1)*h_to_bl)) / h_to_bl
3355 endif
33560 if (dSpice_lim * dSpice_2dz <= 0.0) dSpice_2dz = 0.0
3357
33580 if (stays > 0.0) then
3359 ! Limit the spiciness of the water that stays in the upper buffer layer.
33600 if (abs(dSpice_lim) < abs(dSpice_2dz*(h1_to_k0 + h1_to_h2))) &
33610 dSpice_2dz = dSpice_lim/(h1_to_k0 + h1_to_h2)
3362
33630 dSpice_stays = dSpice_2dz*(h1_to_k0 + h1_to_h2)
3364 T_stays = T(i,kb1) + dT_dS_gauge * I_denom * &
33650 (dT_dS_gauge * dRcv_dT(i) * dRcv_stays + dRcv_dS(i) * dSpice_stays)
3366 S_stays = S(i,kb1) + I_denom * &
33670 (dRcv_dS(i) * dRcv_stays - dT_dS_gauge * dRcv_dT(i) * dSpice_stays)
3368 ! The values of R0 or SpV0 are based on changes in T and S.
33690 if (CS%nonBous_energetics) then
3370 SpV0_stays = SpV0(i,kb1) + (T_stays-T(i,kb1)) * dSpV0_dT(i) + &
33710 (S_stays-S(i,kb1)) * dSpV0_dS(i)
3372 else
3373 R0_stays = R0(i,kb1) + (T_stays-T(i,kb1)) * dR0_dT(i) + &
33740 (S_stays-S(i,kb1)) * dR0_dS(i)
3375 endif
3376 else
3377 ! Limit the spiciness of the water that moves into the lower buffer layer.
33780 if (abs(dSpice_lim) < abs(dSpice_2dz*h1_to_k0)) &
33790 dSpice_2dz = dSpice_lim/h1_to_k0
3380 ! These will be multiplied by 0 later.
33810 T_stays = 0.0 ; S_stays = 0.0 ; R0_stays = 0.0 ; SpV0_stays = 0.0
3382 endif
3383
33840 dSpice_det = - dSpice_2dz*(stays + h1_to_h2)
3385 T_det = T(i,kb1) + dT_dS_gauge * I_denom * &
33860 (dT_dS_gauge * dRcv_dT(i) * dRcv_det + dRcv_dS(i) * dSpice_det)
3387 S_det = S(i,kb1) + I_denom * &
33880 (dRcv_dS(i) * dRcv_det - dT_dS_gauge * dRcv_dT(i) * dSpice_det)
3389 ! The values of R0 or SpV0 are based on changes in T and S.
33900 if (CS%nonBous_energetics) then
3391 SpV0_det = SpV0(i,kb1) + (T_det-T(i,kb1)) * dSpV0_dT(i) + &
33920 (S_det-S(i,kb1)) * dSpV0_dS(i)
3393 else
3394 R0_det = R0(i,kb1) + (T_det-T(i,kb1)) * dR0_dT(i) + &
33950 (S_det-S(i,kb1)) * dR0_dS(i)
3396 endif
3397
33980 T(i,k0) = ((h1_to_k0*T_det + h2*T(i,kb2)) + h(i,k0)*T(i,k0)) * Ihk0
33990 T(i,kb2) = (h1*T(i,kb1) - stays*T_stays - h1_to_k0*T_det) * Ih2f
34000 T(i,kb1) = (T_to_bl + stays*T_stays) * Ih1f
3401
34020 S(i,k0) = ((h1_to_k0*S_det + h2*S(i,kb2)) + h(i,k0)*S(i,k0)) * Ihk0
34030 S(i,kb2) = (h1*S(i,kb1) - stays*S_stays - h1_to_k0*S_det) * Ih2f
34040 S(i,kb1) = (S_to_bl + stays*S_stays) * Ih1f
3405
34060 if (CS%nonBous_energetics) then
34070 SpV0(i,k0) = ((h1_to_k0*SpV0_det + h2*SpV0(i,kb2)) + h(i,k0)*SpV0(i,k0)) * Ihk0
34080 SpV0(i,kb2) = (h1*SpV0(i,kb1) - stays*SpV0_stays - h1_to_k0*SpV0_det) * Ih2f
34090 SpV0(i,kb1) = (SpV0_to_bl + stays*SpV0_stays) * Ih1f
3410 else
34110 R0(i,k0) = ((h1_to_k0*R0_det + h2*R0(i,kb2)) + h(i,k0)*R0(i,k0)) * Ihk0
34120 R0(i,kb2) = (h1*R0(i,kb1) - stays*R0_stays - h1_to_k0*R0_det) * Ih2f
34130 R0(i,kb1) = (R0_to_bl + stays*R0_stays) * Ih1f
3414 endif
3415
3416! ! The following is 2nd-order upwind advection without limiters.
3417! dT_2dz = (T(i,kb1) - T(i,kb2)) * Ih12
3418! T(i,k0) = (h1_to_k0*(T(i,kb1) - dT_2dz*(stays+h1_to_h2)) + &
3419! h2*T(i,kb2) + h(i,k0)*T(i,k0)) * Ihk0
3420! T(i,kb2) = T(i,kb1) + dT_2dz*(h1_to_k0-stays)
3421! T(i,kb1) = (T_to_bl + stays*(T(i,kb1) + dT_2dz*(h1_to_k0 + h1_to_h2))) * Ih1f
3422! dS_2dz = (S(i,kb1) - S(i,kb2)) * Ih12
3423! S(i,k0) = (h1_to_k0*(S(i,kb1) - dS_2dz*(stays+h1_to_h2)) + &
3424! h2*S(i,kb2) + h(i,k0)*S(i,k0)) * Ihk0
3425! S(i,kb2) = S(i,kb1) + dS_2dz*(h1_to_k0-stays)
3426! S(i,kb1) = (S_to_bl + stays*(S(i,kb1) + dS_2dz*(h1_to_k0 + h1_to_h2))) * Ih1f
3427! if (CS%nonBous_energetics) then
3428! dSpV0_2dz = (SpV0(i,kb1) - SpV0(i,kb2)) * Ih12
3429! SpV0(i,k0) = (h1_to_k0*(SpV0(i,kb1) - dSpV0_2dz*(stays+h1_to_h2)) + &
3430! h2*SpV0(i,kb2) + h(i,k0)*SpV0(i,k0)) * Ihk0
3431! SpV0(i,kb2) = SpV0(i,kb1) + dSpV0_2dz*(h1_to_k0-stays)
3432! SpV0(i,kb1) = (SpV0_to_bl + stays*(SpV0(i,kb1) + dSpV0_2dz*(h1_to_k0 + h1_to_h2))) * Ih1f
3433! else
3434! dR0_2dz = (R0(i,kb1) - R0(i,kb2)) * Ih12
3435! R0(i,k0) = (h1_to_k0*(R0(i,kb1) - dR0_2dz*(stays+h1_to_h2)) + &
3436! h2*R0(i,kb2) + h(i,k0)*R0(i,k0)) * Ihk0
3437! R0(i,kb2) = R0(i,kb1) + dR0_2dz*(h1_to_k0-stays)
3438! R0(i,kb1) = (R0_to_bl + stays*(R0(i,kb1) + dR0_2dz*(h1_to_k0 + h1_to_h2))) * Ih1f
3439! endif
3440
34410 d_ea(i,kb1) = (d_ea(i,kb1) + h_to_bl) + (stays - h1)
34420 d_ea(i,kb2) = d_ea(i,kb2) + (h1_to_h2 - h2)
34430 d_ea(i,k0) = d_ea(i,k0) + (h1_to_k0 + h2)
3444
34450 h(i,kb1) = stays + h_to_bl
34460 h(i,kb2) = h1_to_h2
34470 h(i,k0) = h(i,k0) + (h1_to_k0 + h2)
34480 if (CS%nonBous_energetics) then
34490 if (allocated(CS%diag_PE_detrain)) &
34500 CS%diag_PE_detrain(i,j) = CS%diag_PE_detrain(i,j) + Idt_diag*dPE_merge_nB
34510 if (allocated(CS%diag_PE_detrain2)) CS%diag_PE_detrain2(i,j) = &
34520 CS%diag_PE_detrain2(i,j) + Idt_diag*(dPE_det_nB + dPE_extrapolate)
3453 else
34540 if (allocated(CS%diag_PE_detrain)) &
34550 CS%diag_PE_detrain(i,j) = CS%diag_PE_detrain(i,j) + Idt_H2*dPE_merge
34560 if (allocated(CS%diag_PE_detrain2)) CS%diag_PE_detrain2(i,j) = &
34570 CS%diag_PE_detrain2(i,j) + Idt_H2*(dPE_det + Rho0xG*dPE_extrap_rhoG)
3458 endif
3459 else ! Not mergeable_bl.
3460 ! There is no further detrainment from the buffer layers, and the
3461 ! upper buffer layer water is distributed optimally between the
3462 ! upper and lower buffer layer.
34632 h1_to_h2 = h1 - stays
34642 Ih1f = 1.0 / (h_to_bl + stays) ; Ih2f = 1.0 / (h2 + h1_to_h2)
34652 Ih = 1.0 / (h1 + h2)
34662 if (CS%nonBous_energetics) then
34670 dSpV0_2dz = (SpV0(i,kb1) - SpV0(i,kb2)) * Ih
34680 SpV0(i,kb2) = (h2*SpV0(i,kb2) + h1_to_h2*(SpV0(i,kb1) - scale_slope*dSpV0_2dz*stays)) * Ih2f
34690 SpV0(i,kb1) = (SpV0_to_bl + stays*(SpV0(i,kb1) + scale_slope*dSpV0_2dz*h1_to_h2)) * Ih1f
3470 else
34712 dR0_2dz = (R0(i,kb1) - R0(i,kb2)) * Ih
34722 R0(i,kb2) = (h2*R0(i,kb2) + h1_to_h2*(R0(i,kb1) - scale_slope*dR0_2dz*stays)) * Ih2f
34732 R0(i,kb1) = (R0_to_bl + stays*(R0(i,kb1) + scale_slope*dR0_2dz*h1_to_h2)) * Ih1f
3474 endif
3475
3476 ! Use 2nd order upwind advection of spiciness, limited by the value in the
3477 ! detrained water to determine the detrained temperature and salinity.
34782 if (CS%nonBous_energetics) then
34790 dSpV0 = scale_slope*dSpV0_2dz*h1_to_h2
3480 dSpiceSpV_stays = (dS_dT_gauge*dSpV0_dS(i)*(T(i,kb1)-T(i,kb2)) - &
3481 dT_dS_gauge*dSpV0_dT(i)*(S(i,kb1)-S(i,kb2))) * &
34820 scale_slope*h1_to_h2 * Ih
34830 if (h_to_bl > 0.0) then
3484 dSpiceSpV_lim = (dS_dT_gauge*dSpV0_dS(i)*(T_to_bl-T(i,kb1)*h_to_bl) - &
34850 dT_dS_gauge*dSpV0_dT(i)*(S_to_bl-S(i,kb1)*h_to_bl)) / h_to_bl
3486 else
3487 dSpiceSpV_lim = dS_dT_gauge*dSpV0_dS(i)*(T(i,0)-T(i,kb1)) - &
34880 dT_dS_gauge*dSpV0_dT(i)*(S(i,0)-S(i,kb1))
3489 endif
34900 if (dSpiceSpV_stays*dSpiceSpV_lim <= 0.0) then
34910 dSpiceSpV_stays = 0.0
34920 elseif (abs(dSpiceSpV_stays) > abs(dSpiceSpV_lim)) then
34930 dSpiceSpV_stays = dSpiceSpV_lim
3494 endif
34950 I_denom = 1.0 / (dSpV0_dS(i)**2 + (dT_dS_gauge*dSpV0_dT(i))**2)
3496 T_stays = T(i,kb1) + dT_dS_gauge * I_denom * &
34970 (dT_dS_gauge * dSpV0_dT(i) * dSpV0 + dSpV0_dS(i) * dSpiceSpV_stays)
3498 S_stays = S(i,kb1) + I_denom * &
34990 (dSpV0_dS(i) * dSpV0 - dT_dS_gauge * dSpV0_dT(i) * dSpiceSpV_stays)
3500 else
35012 dR0 = scale_slope*dR0_2dz*h1_to_h2
3502 dSpice_stays = (dS_dT_gauge*dR0_dS(i)*(T(i,kb1)-T(i,kb2)) - &
3503 dT_dS_gauge*dR0_dT(i)*(S(i,kb1)-S(i,kb2))) * &
35042 scale_slope*h1_to_h2 * Ih
35052 if (h_to_bl > 0.0) then
3506 dSpice_lim = (dS_dT_gauge*dR0_dS(i)*(T_to_bl-T(i,kb1)*h_to_bl) - &
35072 dT_dS_gauge*dR0_dT(i)*(S_to_bl-S(i,kb1)*h_to_bl)) / h_to_bl
3508 else
3509 dSpice_lim = dS_dT_gauge*dR0_dS(i)*(T(i,0)-T(i,kb1)) - &
35100 dT_dS_gauge*dR0_dT(i)*(S(i,0)-S(i,kb1))
3511 endif
35122 if (dSpice_stays*dSpice_lim <= 0.0) then
35132 dSpice_stays = 0.0
35140 elseif (abs(dSpice_stays) > abs(dSpice_lim)) then
35150 dSpice_stays = dSpice_lim
3516 endif
35172 I_denom = 1.0 / (dR0_dS(i)**2 + (dT_dS_gauge*dR0_dT(i))**2)
3518 T_stays = T(i,kb1) + dT_dS_gauge * I_denom * &
35192 (dT_dS_gauge * dR0_dT(i) * dR0 + dR0_dS(i) * dSpice_stays)
3520 S_stays = S(i,kb1) + I_denom * &
35212 (dR0_dS(i) * dR0 - dT_dS_gauge * dR0_dT(i) * dSpice_stays)
3522 endif
3523
3524 ! The detrained values of Rcv are based on changes in T and S.
3525 Rcv_stays = Rcv(i,kb1) + (T_stays-T(i,kb1)) * dRcv_dT(i) + &
35262 (S_stays-S(i,kb1)) * dRcv_dS(i)
3527
35282 T(i,kb2) = (h2*T(i,kb2) + h1*T(i,kb1) - T_stays*stays) * Ih2f
35292 T(i,kb1) = (T_to_bl + stays*T_stays) * Ih1f
35302 S(i,kb2) = (h2*S(i,kb2) + h1*S(i,kb1) - S_stays*stays) * Ih2f
35312 S(i,kb1) = (S_to_bl + stays*S_stays) * Ih1f
35322 Rcv(i,kb2) = (h2*Rcv(i,kb2) + h1*Rcv(i,kb1) - Rcv_stays*stays) * Ih2f
35332 Rcv(i,kb1) = (Rcv_to_bl + stays*Rcv_stays) * Ih1f
3534
3535! ! The following is 2nd-order upwind advection without limiters.
3536! dRcv_2dz = (Rcv(i,kb1) - Rcv(i,kb2)) * Ih
3537! dRcv = scale_slope*dRcv_2dz*h1_to_h2
3538! Rcv(i,kb2) = (h2*Rcv(i,kb2) + h1_to_h2*(Rcv(i,kb1) - &
3539! scale_slope*dRcv_2dz*stays)) * Ih2f
3540! Rcv(i,kb1) = (Rcv_to_bl + stays*(Rcv(i,kb1) + dRcv)) * Ih1f
3541! dT_2dz = (T(i,kb1) - T(i,kb2)) * Ih
3542! T(i,kb2) = (h2*T(i,kb2) + h1_to_h2*(T(i,kb1) - &
3543! scale_slope*dT_2dz*stays)) * Ih2f
3544! T(i,kb1) = (T_to_bl + stays*(T(i,kb1) + &
3545! scale_slope*dT_2dz*h1_to_h2)) * Ih1f
3546! dS_2dz = (S(i,kb1) - S(i,kb2)) * Ih
3547! S(i,kb2) = (h2*S(i,kb2) + h1_to_h2*(S(i,kb1) - &
3548! scale_slope*dS_2dz*stays)) * Ih2f
3549! S(i,kb1) = (S_to_bl + stays*(S(i,kb1) + &
3550! scale_slope*dS_2dz*h1_to_h2)) * Ih1f
3551
35522 d_ea(i,kb1) = d_ea(i,kb1) + ((stays - h1) + h_to_bl)
35532 d_ea(i,kb2) = d_ea(i,kb2) + h1_to_h2
3554
35552 h(i,kb1) = stays + h_to_bl
35562 h(i,kb2) = h(i,kb2) + h1_to_h2
3557
35582 if (CS%nonBous_energetics) then
35590 if (allocated(CS%diag_PE_detrain)) &
35600 CS%diag_PE_detrain(i,j) = CS%diag_PE_detrain(i,j) + Idt_diag*dPE_det_nB
35610 if (allocated(CS%diag_PE_detrain2)) CS%diag_PE_detrain2(i,j) = &
35620 CS%diag_PE_detrain2(i,j) + Idt_diag*(dPE_det_nB + dPE_extrapolate)
3563 else
3564 ! Recasting dPE_det into the same units as dPE_det_nB changes these diagnostics slightly
3565 ! in some cases for reasons that are not understood.
35662 if (allocated(CS%diag_PE_detrain)) &
35670 CS%diag_PE_detrain(i,j) = CS%diag_PE_detrain(i,j) + Idt_H2*dPE_det
35682 if (allocated(CS%diag_PE_detrain2)) CS%diag_PE_detrain2(i,j) = &
35690 CS%diag_PE_detrain2(i,j) + Idt_H2*(dPE_det + Rho0xG*dPE_extrap_rhoG)
3570 endif
3571 endif
3572 endif ! End of detrainment...
3573
3574 enddo ! i loop
3575
3576180end subroutine mixedlayer_detrain_2
3577
3578!> This subroutine moves any water left in the former mixed layers into the
3579!! single buffer layers and may also move buffer layer water into the interior
3580!! isopycnal layers.
35810subroutine mixedlayer_detrain_1(h, T, S, R0, SpV0, Rcv, RcvTgt, dt, dt_diag, d_ea, d_eb, &
35820 j, G, GV, US, CS, dRcv_dT, dRcv_dS, max_BL_det)
3583 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
3584 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
3585 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2].
3586 !! Layer 0 is the new mixed layer.
3587 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: T !< Potential temperature [C ~> degC].
3588 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: S !< Salinity [S ~> ppt].
3589 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: R0 !< Potential density referenced to
3590 !! surface pressure [R ~> kg m-3].
3591 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: SpV0 !< Specific volume referenced to
3592 !! surface pressure [R-1 ~> m3 kg-1]
3593 real, dimension(SZI_(G),SZK0_(GV)), intent(inout) :: Rcv !< The coordinate defining potential
3594 !! density [R ~> kg m-3].
3595 real, dimension(SZK_(GV)), intent(in) :: RcvTgt !< The target value of Rcv for each
3596 !! layer [R ~> kg m-3].
3597 real, intent(in) :: dt !< Time increment [T ~> s].
3598 real, intent(in) :: dt_diag !< The accumulated time interval for
3599 !! diagnostics [T ~> s].
3600 real, dimension(SZI_(G),SZK_(GV)), intent(inout) :: d_ea !< The upward increase across a layer in
3601 !! the entrainment from above
3602 !! [H ~> m or kg m-2]. Positive d_ea
3603 !! goes with layer thickness increases.
3604 real, dimension(SZI_(G),SZK_(GV)), intent(inout) :: d_eb !< The downward increase across a layer
3605 !! in the entrainment from below [H ~> m or kg m-2].
3606 !! Positive values go with mass gain by
3607 !! a layer.
3608 integer, intent(in) :: j !< The meridional row to work on.
3609 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
3610 type(bulkmixedlayer_CS), intent(inout) :: CS !< Bulk mixed layer control structure
3611 real, dimension(SZI_(G)), intent(in) :: dRcv_dT !< The partial derivative of
3612 !! coordinate defining potential density
3613 !! with potential temperature
3614 !! [R C-1 ~> kg m-3 degC-1].
3615 real, dimension(SZI_(G)), intent(in) :: dRcv_dS !< The partial derivative of
3616 !! coordinate defining potential density
3617 !! with salinity [R S-1 ~> kg m-3 ppt-1].
3618 real, dimension(SZI_(G)), intent(in) :: max_BL_det !< If non-negative, the maximum
3619 !! detrainment permitted from the buffer
3620 !! layers [H ~> m or kg m-2].
3621
3622 ! Local variables
3623 real :: Ih ! The inverse of a thickness [H-1 ~> m-1 or m2 kg-1].
3624 real :: h_ent ! The thickness from a layer that is
3625 ! entrained [H ~> m or kg m-2].
36260 real :: max_det_rem(SZI_(G)) ! Remaining permitted detrainment [H ~> m or kg m-2].
36270 real :: detrain(SZI_(G)) ! The thickness of fluid to detrain
3628 ! from the mixed layer [H ~> m or kg m-2].
3629 real :: dT_dS_wt2 ! The square of the relative weighting of temperature and salinity changes
3630 ! when extraploating to match a target density [C2 S-2 ~> degC2 ppt-2]
3631 real :: dT_dR ! The ratio of temperature changes to density changes when
3632 ! extrapolating [C R-1 ~> degC m3 kg-1]
3633 real :: dS_dR ! The ratio of salinity changes to density changes when
3634 ! extrapolating [S R-1 ~> ppt m3 kg-1]
3635 real :: dRml ! The density range within the extent of the mixed layers [R ~> kg m-3]
3636 real :: dR0_dRcv ! The relative changes in the potential density and the coordinate density [nondim]
3637 real :: dSpV0_dRcv ! The relative changes in the specific volume and the coordinate density [R-2 ~> m6 kg-2]
3638 real :: I_denom ! A work variable [S2 R-2 ~> ppt2 m6 kg-2].
3639 real :: Sdown ! The salinity of the detrained water [S ~> ppt]
3640 real :: Tdown ! The temperature of the detrained water [C ~> degC]
3641 real :: dt_Time ! The timestep divided by the detrainment timescale [nondim].
3642 real :: g_H_2Rho0dt ! Half the gravitational acceleration times the
3643 ! conversion from H to m divided by the mean density times the time
3644 ! step [Z2 T-3 H-1 R-1 ~> m4 s-3 kg-1 or m7 s-3 kg-2].
3645 real :: g_H2_2dt ! Half the gravitational acceleration times the square of the
3646 ! conversion from H to Z divided by the diagnostic time step
3647 ! [Z3 H-2 T-3 ~> m s-3 or m7 kg-2 s-3].
3648 real :: nB_g_H_2dt ! Half the gravitational acceleration times the conversion from
3649 ! H to RZ divided by the diagnostic time step
3650 ! [R Z2 H-1 T-3 ~> kg m-2 s-3 or m s-3].
3651 real :: nB_gRZ_H2_2dt ! Half the gravitational acceleration times the conversion from
3652 ! H to RZ squared divided by the diagnostic time step
3653 ! [R2 Z3 H-2 T-3 ~> kg2 m-5 s-3 or m s-3]
3654 real :: x1 ! A temporary work variable [various]
36550 logical :: splittable_BL(SZI_(G)), orthogonal_extrap
3656 logical :: must_unmix
3657 integer :: i, is, ie, k, k1, nkmb, nz
3658
36590 is = G%isc ; ie = G%iec ; nz = GV%ke
36600 nkmb = CS%nkml+CS%nkbl
36610 if (CS%nkbl /= 1) call MOM_error(FATAL,"MOM_mixed_layer: "// &
36620 "CS%nkbl must be 1 in mixedlayer_detrain_1.")
3663
36640 dt_Time = dt / CS%BL_detrain_time
3665
36660 if (CS%nonBous_energetics) then
36670 nB_g_H_2dt = (GV%g_Earth_Z_T2 * GV%H_to_RZ) / (2.0 * dt_diag)
36680 nB_gRZ_H2_2dt = GV%H_to_RZ * nB_g_H_2dt
3669 else
36700 g_H2_2dt = (GV%g_Earth_Z_T2 * GV%H_to_Z**2) / (2.0 * dt_diag)
36710 g_H_2Rho0dt = g_H2_2dt * GV%RZ_to_H
3672 endif
3673
3674 ! Move detrained water into the buffer layer.
36750 do k=1,CS%nkml
36760 do i=is,ie ; if (h(i,k) > 0.0) then
36770 Ih = 1.0 / (h(i,nkmb) + h(i,k))
3678
36790 if (CS%nonBous_energetics) then
36800 if (CS%TKE_diagnostics) &
3681 CS%diag_TKE_conv_s2(i,j) = CS%diag_TKE_conv_s2(i,j) - &
36820 nB_g_H_2dt * (h(i,k) * h(i,nkmb)) * (SpV0(i,nkmb) - SpV0(i,k))
36830 if (allocated(CS%diag_PE_detrain)) &
3684 CS%diag_PE_detrain(i,j) = CS%diag_PE_detrain(i,j) - &
36850 nB_gRZ_H2_2dt * (h(i,k) * h(i,nkmb)) * (SpV0(i,nkmb) - SpV0(i,k))
36860 if (allocated(CS%diag_PE_detrain2)) &
3687 CS%diag_PE_detrain2(i,j) = CS%diag_PE_detrain2(i,j) - &
36880 nB_gRZ_H2_2dt * (h(i,k) * h(i,nkmb)) * (SpV0(i,nkmb) - SpV0(i,k))
3689
36900 SpV0(i,nkmb) = (SpV0(i,nkmb)*h(i,nkmb) + SpV0(i,k)*h(i,k)) * Ih
3691 else
36920 if (CS%TKE_diagnostics) &
3693 CS%diag_TKE_conv_s2(i,j) = CS%diag_TKE_conv_s2(i,j) + &
36940 g_H_2Rho0dt * h(i,k) * h(i,nkmb) * (R0(i,nkmb) - R0(i,k))
36950 if (allocated(CS%diag_PE_detrain)) &
3696 CS%diag_PE_detrain(i,j) = CS%diag_PE_detrain(i,j) + &
36970 g_H2_2dt * h(i,k) * h(i,nkmb) * (R0(i,nkmb) - R0(i,k))
36980 if (allocated(CS%diag_PE_detrain2)) &
3699 CS%diag_PE_detrain2(i,j) = CS%diag_PE_detrain2(i,j) + &
37000 g_H2_2dt * h(i,k) * h(i,nkmb) * (R0(i,nkmb) - R0(i,k))
3701
37020 R0(i,nkmb) = (R0(i,nkmb)*h(i,nkmb) + R0(i,k)*h(i,k)) * Ih
3703 endif
37040 Rcv(i,nkmb) = (Rcv(i,nkmb)*h(i,nkmb) + Rcv(i,k)*h(i,k)) * Ih
37050 T(i,nkmb) = (T(i,nkmb)*h(i,nkmb) + T(i,k)*h(i,k)) * Ih
37060 S(i,nkmb) = (S(i,nkmb)*h(i,nkmb) + S(i,k)*h(i,k)) * Ih
3707
37080 d_ea(i,k) = d_ea(i,k) - h(i,k)
37090 d_ea(i,nkmb) = d_ea(i,nkmb) + h(i,k)
37100 h(i,nkmb) = h(i,nkmb) + h(i,k)
37110 h(i,k) = 0.0
3712 endif ; enddo
3713 enddo
3714
37150 do i=is,ie
37160 max_det_rem(i) = 10.0 * h(i,nkmb)
37170 if (max_BL_det(i) >= 0.0) max_det_rem(i) = max_BL_det(i)
3718 enddo
3719
3720! If the mixed layer was denser than the densest interior layer,
3721! but is now lighter than this layer, leaving a buffer layer that
3722! is denser than this layer, there are problems. This should prob-
3723! ably be considered a case of an inadequate choice of resolution in
3724! density space and should be avoided. To make the model run sens-
3725! ibly in this case, it will make the mixed layer denser while making
3726! the buffer layer the density of the densest interior layer (pro-
3727! vided that the this will not make the mixed layer denser than the
3728! interior layer). Otherwise, make the mixed layer the same density
3729! as the densest interior layer and lighten the buffer layer with
3730! the released buoyancy. With multiple buffer layers, much more
3731! graceful options are available.
37320 do i=is,ie ; if (h(i,nkmb) > 0.0) then
37330 if (CS%nonBous_energetics) then
37340 must_unmix = (SpV0(i,0) > SpV0(i,nz)) .and. (SpV0(i,nz) > SpV0(i,nkmb))
3735 else
37360 must_unmix = (R0(i,0) < R0(i,nz)) .and. (R0(i,nz) < R0(i,nkmb))
3737 endif
37380 if (must_unmix) then
37390 if (CS%nonBous_energetics) then
37400 if ((SpV0(i,0)-SpV0(i,nz))*h(i,0) > (SpV0(i,nz)-SpV0(i,nkmb))*h(i,nkmb)) then
37410 detrain(i) = (SpV0(i,nz)-SpV0(i,nkmb))*h(i,nkmb) / (SpV0(i,0)-SpV0(i,nkmb))
3742 else
37430 detrain(i) = (SpV0(i,0)-SpV0(i,nz))*h(i,0) / (SpV0(i,0)-SpV0(i,nkmb))
3744 endif
3745 else
37460 if ((R0(i,nz)-R0(i,0))*h(i,0) > (R0(i,nkmb)-R0(i,nz))*h(i,nkmb)) then
37470 detrain(i) = (R0(i,nkmb)-R0(i,nz))*h(i,nkmb) / (R0(i,nkmb)-R0(i,0))
3748 else
37490 detrain(i) = (R0(i,nz)-R0(i,0))*h(i,0) / (R0(i,nkmb)-R0(i,0))
3750 endif
3751 endif
3752
37530 d_eb(i,CS%nkml) = d_eb(i,CS%nkml) + detrain(i)
37540 d_ea(i,CS%nkml) = d_ea(i,CS%nkml) - detrain(i)
37550 d_eb(i,nkmb) = d_eb(i,nkmb) - detrain(i)
37560 d_ea(i,nkmb) = d_ea(i,nkmb) + detrain(i)
3757
37580 if (CS%nonBous_energetics) then
37590 if (allocated(CS%diag_PE_detrain)) CS%diag_PE_detrain(i,j) = &
3760 CS%diag_PE_detrain(i,j) - nB_gRZ_H2_2dt * detrain(i)* &
37610 (h(i,0) + h(i,nkmb)) * (SpV0(i,nkmb) - SpV0(i,0))
37620 x1 = SpV0(i,0)
37630 SpV0(i,0) = SpV0(i,0) - detrain(i)*(SpV0(i,0)-SpV0(i,nkmb)) / h(i,0)
37640 SpV0(i,nkmb) = SpV0(i,nkmb) - detrain(i)*(SpV0(i,nkmb)-x1) / h(i,nkmb)
3765 else
37660 if (allocated(CS%diag_PE_detrain)) CS%diag_PE_detrain(i,j) = &
3767 CS%diag_PE_detrain(i,j) + g_H2_2dt * detrain(i)* &
37680 (h(i,0) + h(i,nkmb)) * (R0(i,nkmb) - R0(i,0))
37690 x1 = R0(i,0)
37700 R0(i,0) = R0(i,0) - detrain(i)*(R0(i,0)-R0(i,nkmb)) / h(i,0)
37710 R0(i,nkmb) = R0(i,nkmb) - detrain(i)*(R0(i,nkmb)-x1) / h(i,nkmb)
3772 endif
3773
37740 x1 = Rcv(i,0)
37750 Rcv(i,0) = Rcv(i,0) - detrain(i)*(Rcv(i,0)-Rcv(i,nkmb)) / h(i,0)
37760 Rcv(i,nkmb) = Rcv(i,nkmb) - detrain(i)*(Rcv(i,nkmb)-x1) / h(i,nkmb)
37770 x1 = T(i,0)
37780 T(i,0) = T(i,0) - detrain(i)*(T(i,0)-T(i,nkmb)) / h(i,0)
37790 T(i,nkmb) = T(i,nkmb) - detrain(i)*(T(i,nkmb)-x1) / h(i,nkmb)
37800 x1 = S(i,0)
37810 S(i,0) = S(i,0) - detrain(i)*(S(i,0)-S(i,nkmb)) / h(i,0)
37820 S(i,nkmb) = S(i,nkmb) - detrain(i)*(S(i,nkmb)-x1) / h(i,nkmb)
3783
3784 endif
3785 endif ; enddo
3786
3787 ! Move water out of the buffer layer, if convenient.
3788! Split the buffer layer if possible, and replace the buffer layer
3789! with a small amount of fluid from the mixed layer.
3790! This is the exponential-in-time splitting, circa 2005.
37910 do i=is,ie
37920 if (h(i,nkmb) > 0.0) then ; splittable_BL(i) = .true.
37930 else ; splittable_BL(i) = .false. ; endif
3794 enddo
3795
37960 dT_dS_wt2 = CS%dT_dS_wt**2
3797
37980 do k=nz-1,nkmb+1,-1 ; do i=is,ie
37990 if (splittable_BL(i)) then
38000 if (RcvTgt(k) <= Rcv(i,nkmb)) then
3801! Estimate dR/drho, dTheta/dR, and dS/dR, where R is the coordinate variable
3802! and rho is in-situ (or surface) potential density.
3803! There is no "right" way to do this, so this keeps things reasonable, if
3804! slightly arbitrary.
38050 splittable_BL(i) = .false.
3806
38070 k1 = k+1 ; orthogonal_extrap = .false.
3808 ! Here we try to find a massive layer to use for interpolating the
3809 ! temperature and salinity. If none is available a pseudo-orthogonal
3810 ! extrapolation is used. The 10.0 and 0.9 in the following are
3811 ! arbitrary but probably about right.
38120 if ((h(i,k+1) < 10.0*GV%Angstrom_H) .or. &
3813 ((RcvTgt(k+1)-Rcv(i,nkmb)) >= 0.9*(Rcv(i,k1) - Rcv(i,0)))) then
38140 if (k>=nz-1) then ; orthogonal_extrap = .true.
38150 elseif ((h(i,k+2) <= 10.0*GV%Angstrom_H) .and. &
3816 ((RcvTgt(k+1)-Rcv(i,nkmb)) < 0.9*(Rcv(i,k+2)-Rcv(i,0)))) then
38170 k1 = k+2
38180 else ; orthogonal_extrap = .true. ; endif
3819 endif
3820
3821 ! Check for the case when there is an inversion of in-situ density relative to
3822 ! the coordinate variable. Do not detrain from the buffer layer in this case.
38230 if (CS%nonBous_energetics) then
38240 if ((SpV0(i,0) <= SpV0(i,k1)) .or. (Rcv(i,0) >= Rcv(i,nkmb))) cycle
3825 else
38260 if ((R0(i,0) >= R0(i,k1)) .or. (Rcv(i,0) >= Rcv(i,nkmb))) cycle
3827 endif
3828
38290 if (orthogonal_extrap) then
3830 ! 36 here is a typical oceanic value of (dR/dS) / (dR/dT) - it says
3831 ! that the relative weights of T & S changes is a plausible 6:1.
3832 ! Also, this was coded on Athena's 6th birthday!
38330 I_denom = 1.0 / (dRcv_dS(i)**2 + dT_dS_wt2*dRcv_dT(i)**2)
38340 dT_dR = dT_dS_wt2*dRcv_dT(i) * I_denom
38350 dS_dR = dRcv_dS(i) * I_denom
3836 else
38370 dT_dR = (T(i,0) - T(i,k1)) / (Rcv(i,0) - Rcv(i,k1))
38380 dS_dR = (S(i,0) - S(i,k1)) / (Rcv(i,0) - Rcv(i,k1))
3839 endif
3840
38410 if (CS%nonBous_energetics) then
3842 dRml = dt_Time * (SpV0(i,0) - SpV0(i,nkmb)) * &
38430 (Rcv(i,0) - Rcv(i,k1)) / (SpV0(i,k1) - SpV0(i,0))
38440 if (dRml < 0.0) cycle ! Once again, there is an apparent density inversion in Rcv.
38450 dSpV0_dRcv = (SpV0(i,0) - SpV0(i,k1)) / (Rcv(i,0) - Rcv(i,k1))
3846 else
3847 dRml = dt_Time * (R0(i,nkmb) - R0(i,0)) * &
38480 (Rcv(i,0) - Rcv(i,k1)) / (R0(i,0) - R0(i,k1))
38490 if (dRml < 0.0) cycle ! Once again, there is an apparent density inversion in Rcv.
38500 dR0_dRcv = (R0(i,0) - R0(i,k1)) / (Rcv(i,0) - Rcv(i,k1))
3851 endif
3852
38530 if ((Rcv(i,nkmb) - dRml < RcvTgt(k)) .and. (max_det_rem(i) > h(i,nkmb))) then
3854 ! In this case, the buffer layer is split into two isopycnal layers.
3855 detrain(i) = h(i,nkmb) * (Rcv(i,nkmb) - RcvTgt(k)) / &
38560 (RcvTgt(k+1) - RcvTgt(k))
3857
38580 if (allocated(CS%diag_PE_detrain)) then
38590 if (CS%nonBous_energetics) then
3860 CS%diag_PE_detrain(i,j) = CS%diag_PE_detrain(i,j) + nB_gRZ_H2_2dt * detrain(i) * &
38610 (h(i,nkmb)-detrain(i)) * (RcvTgt(k+1) - RcvTgt(k)) * dSpV0_dRcv
3862 else
3863 CS%diag_PE_detrain(i,j) = CS%diag_PE_detrain(i,j) - g_H2_2dt * detrain(i) * &
38640 (h(i,nkmb)-detrain(i)) * (RcvTgt(k+1) - RcvTgt(k)) * dR0_dRcv
3865 endif
3866 endif
3867
38680 Tdown = detrain(i) * (T(i,nkmb) + dT_dR*(RcvTgt(k+1)-Rcv(i,nkmb)))
3869 T(i,k) = (h(i,k) * T(i,k) + &
3870 (h(i,nkmb) * T(i,nkmb) - Tdown)) / &
38710 (h(i,k) + (h(i,nkmb) - detrain(i)))
3872 T(i,k+1) = (h(i,k+1) * T(i,k+1) + Tdown)/ &
38730 (h(i,k+1) + detrain(i))
38740 T(i,nkmb) = T(i,0)
38750 Sdown = detrain(i) * (S(i,nkmb) + dS_dR*(RcvTgt(k+1)-Rcv(i,nkmb)))
3876 S(i,k) = (h(i,k) * S(i,k) + &
3877 (h(i,nkmb) * S(i,nkmb) - Sdown)) / &
38780 (h(i,k) + (h(i,nkmb) - detrain(i)))
3879 S(i,k+1) = (h(i,k+1) * S(i,k+1) + Sdown)/ &
38800 (h(i,k+1) + detrain(i))
38810 S(i,nkmb) = S(i,0)
38820 Rcv(i,nkmb) = Rcv(i,0)
3883
38840 d_ea(i,k+1) = d_ea(i,k+1) + detrain(i)
38850 d_ea(i,k) = d_ea(i,k) + (h(i,nkmb) - detrain(i))
38860 d_ea(i,nkmb) = d_ea(i,nkmb) - h(i,nkmb)
3887
38880 h(i,k+1) = h(i,k+1) + detrain(i)
38890 h(i,k) = h(i,k) + h(i,nkmb) - detrain(i)
38900 h(i,nkmb) = 0.0
3891 else
3892 ! Here only part of the buffer layer is moved into the interior.
38930 detrain(i) = h(i,nkmb) * dRml / (RcvTgt(k+1) - Rcv(i,nkmb) + dRml)
38940 if (detrain(i) > max_det_rem(i)) detrain(i) = max_det_rem(i)
38950 Ih = 1.0 / (h(i,k+1) + detrain(i))
3896
38970 Tdown = (T(i,nkmb) + dT_dR*(RcvTgt(k+1)-Rcv(i,nkmb)))
38980 T(i,nkmb) = T(i,nkmb) - dT_dR * dRml
38990 T(i,k+1) = (h(i,k+1) * T(i,k+1) + detrain(i) * Tdown) * Ih
39000 Sdown = (S(i,nkmb) + dS_dR*(RcvTgt(k+1)-Rcv(i,nkmb)))
3901! The following two expressions updating S(nkmb) are mathematically identical.
3902! S(i,nkmb) = (h(i,nkmb) * S(i,nkmb) - detrain(i) * Sdown) / &
3903! (h(i,nkmb) - detrain(i))
39040 S(i,nkmb) = S(i,nkmb) - dS_dR * dRml
39050 S(i,k+1) = (h(i,k+1) * S(i,k+1) + detrain(i) * Sdown) * Ih
3906
39070 d_ea(i,k+1) = d_ea(i,k+1) + detrain(i)
39080 d_ea(i,nkmb) = d_ea(i,nkmb) - detrain(i)
3909
39100 h(i,k+1) = h(i,k+1) + detrain(i)
39110 h(i,nkmb) = h(i,nkmb) - detrain(i)
3912
39130 if (allocated(CS%diag_PE_detrain)) then
39140 if (CS%nonBous_energetics) then
3915 CS%diag_PE_detrain(i,j) = CS%diag_PE_detrain(i,j) + nB_gRZ_H2_2dt * detrain(i) * dSpV0_dRcv * &
39160 (h(i,nkmb)-detrain(i)) * (RcvTgt(k+1) - Rcv(i,nkmb) + dRml)
3917 else
3918 CS%diag_PE_detrain(i,j) = CS%diag_PE_detrain(i,j) - g_H2_2dt * detrain(i) * dR0_dRcv * &
39190 (h(i,nkmb)-detrain(i)) * (RcvTgt(k+1) - Rcv(i,nkmb) + dRml)
3920 endif
3921 endif
3922 endif
3923 endif ! (RcvTgt(k) <= Rcv(i,nkmb))
3924 endif ! splittable_BL
3925 enddo ; enddo ! i & k loops
3926
3927! The numerical behavior of the buffer layer is dramatically improved
3928! if it is always at least a small fraction (say 10%) of the thickness
3929! of the mixed layer. As the physical distinction between the mixed
3930! and buffer layers is vague anyway, this seems hard to argue against.
39310 do i=is,ie
39320 if (h(i,nkmb) < 0.1*h(i,0)) then
39330 h_ent = 0.1*h(i,0) - h(i,nkmb)
39340 Ih = 10.0/h(i,0)
39350 T(i,nkmb) = (h(i,nkmb)*T(i,nkmb) + h_ent*T(i,0)) * Ih
39360 S(i,nkmb) = (h(i,nkmb)*S(i,nkmb) + h_ent*S(i,0)) * Ih
3937
39380 d_ea(i,1) = d_ea(i,1) - h_ent
39390 d_ea(i,nkmb) = d_ea(i,nkmb) + h_ent
3940
39410 h(i,0) = h(i,0) - h_ent
39420 h(i,nkmb) = h(i,nkmb) + h_ent
3943 endif
3944 enddo
3945
39460end subroutine mixedlayer_detrain_1
3947
3948!> This subroutine initializes the MOM bulk mixed layer module.
39491subroutine bulkmixedlayer_init(Time, G, GV, US, param_file, diag, CS)
3950 type(time_type), target, intent(in) :: Time !< The model's clock with the current time.
3951 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
3952 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
3953 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
3954 type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time
3955 !! parameters.
3956 type(diag_ctrl), target, intent(inout) :: diag !< A structure that is used to regulate diagnostic
3957 !! output.
3958 type(bulkmixedlayer_CS), intent(inout) :: CS !< Bulk mixed layer control structure
3959
3960 ! This include declares and sets the variable "version".
3961# include "version_variable.h"
3962 character(len=40) :: mdl = "MOM_mixed_layer" ! This module's name.
3963 real :: omega_frac_dflt ! The default value for ML_OMEGA_FRAC [nondim]
3964 real :: ustar_min_dflt ! The default value for BML_USTAR_MIN [Z T-1 ~> m s-1]
3965 real :: Hmix_min_z ! HMIX_MIN in units of vertical extent [Z ~> m], used to set other defaults
3966 integer :: isd, ied, jsd, jed
3967 logical :: use_temperature, use_omega
39681 isd = G%isd ; ied = G%ied ; jsd = G%jsd ; jed = G%jed
3969
39701 CS%initialized = .true.
39711 CS%diag => diag
39721 CS%Time => Time
3973
39741 if (GV%nkml < 1) return
3975
3976! Set default, read and log parameters
39771 call log_version(param_file, mdl, version, "")
3978
39791 CS%nkml = GV%nkml
3980 call log_param(param_file, mdl, "NKML", CS%nkml, &
3981 "The number of sublayers within the mixed layer if "//&
39821 "BULKMIXEDLAYER is true.", units="nondim", default=2)
39831 CS%nkbl = GV%nk_rho_varies - GV%nkml
3984 call log_param(param_file, mdl, "NKBL", CS%nkbl, &
3985 "The number of variable density buffer layers if "//&
39861 "BULKMIXEDLAYER is true.", units="nondim", default=2)
3987 call get_param(param_file, mdl, "MSTAR", CS%mstar, &
3988 "The ratio of the friction velocity cubed to the TKE "//&
39891 "input to the mixed layer.", units="nondim", default=1.2)
3990 call get_param(param_file, mdl, "NSTAR", CS%nstar, &
3991 "The portion of the buoyant potential energy imparted by "//&
3992 "surface fluxes that is available to drive entrainment "//&
3993 "at the base of mixed layer when that energy is positive.", &
39941 units="nondim", default=0.15)
3995 call get_param(param_file, mdl, "BULK_RI_ML", CS%bulk_Ri_ML, &
3996 "The efficiency with which mean kinetic energy released "//&
3997 "by mechanically forced entrainment of the mixed layer "//&
3998 "is converted to turbulent kinetic energy.", &
39991 units="nondim", fail_if_missing=.true., scale=US%L_to_Z**2)
4000 call get_param(param_file, mdl, "ABSORB_ALL_SW", CS%absorb_all_sw, &
4001 "If true, all shortwave radiation is absorbed by the "//&
4002 "ocean, instead of passing through to the bottom mud.", &
40031 default=.false.)
4004 call get_param(param_file, mdl, "TKE_DECAY", CS%TKE_decay, &
4005 "TKE_DECAY relates the vertical rate of decay of the "//&
4006 "TKE available for mechanical entrainment to the natural "//&
40071 "Ekman depth.", units="nondim", default=2.5)
4008 call get_param(param_file, mdl, "NSTAR2", CS%nstar2, &
4009 "The portion of any potential energy released by "//&
4010 "convective adjustment that is available to drive "//&
4011 "entrainment at the base of mixed layer. By default NSTAR2=NSTAR.", &
40121 units="nondim", default=CS%nstar)
4013 call get_param(param_file, mdl, "BULK_RI_CONVECTIVE", CS%bulk_Ri_convective, &
4014 "The efficiency with which convectively released mean "//&
4015 "kinetic energy is converted to turbulent kinetic "//&
4016 "energy. By default BULK_RI_CONVECTIVE=BULK_RI_ML.", &
40171 units="nondim", default=US%Z_to_L**2*CS%bulk_Ri_ML, scale=US%L_to_Z**2)
4018 call get_param(param_file, mdl, 'VON_KARMAN_CONST', CS%vonKar, &
4019 'The value the von Karman constant as used for mixed layer viscosity.', &
40201 units='nondim', default=0.41)
4021 call get_param(param_file, mdl, "HMIX_MIN", Hmix_min_Z, &
4022 "The minimum mixed layer depth if the mixed layer depth "//&
40231 "is determined dynamically.", units="m", default=0.0, scale=US%m_to_Z)
40241 CS%Hmix_min = GV%m_to_H * (US%Z_to_m * Hmix_min_Z)
4025 call get_param(param_file, mdl, "MECH_TKE_FLOOR", CS%mech_TKE_floor, &
4026 "A tiny floor on the amount of turbulent kinetic energy that is used when "//&
4027 "the mixed layer does not yet contain HMIX_MIN fluid. The default is so "//&
4028 "small that its actual value is irrelevant, so long as it is greater than 0.", &
4029 units="m3 s-2", default=1.0e-150, scale=GV%m_to_H*US%m_s_to_L_T**2*US%L_to_Z**2, &
40301 do_not_log=(Hmix_min_Z<=0.0))
4031
4032 call get_param(param_file, mdl, "LIMIT_BUFFER_DETRAIN", CS%limit_det, &
4033 "If true, limit the detrainment from the buffer layers "//&
40341 "to not be too different from the neighbors.", default=.false.)
4035 call get_param(param_file, mdl, "ALLOWED_DETRAIN_TEMP_CHG", CS%Allowed_T_chg, &
4036 "The amount by which temperature is allowed to exceed previous values "//&
40371 "during detrainment.", units="K", default=0.5, scale=US%degC_to_C)
4038 call get_param(param_file, mdl, "ALLOWED_DETRAIN_SALT_CHG", CS%Allowed_S_chg, &
4039 "The amount by which salinity is allowed to exceed previous values "//&
40401 "during detrainment.", units="ppt", default=0.1, scale=US%ppt_to_S)
4041 call get_param(param_file, mdl, "ML_DT_DS_WEIGHT", CS%dT_dS_wt, &
4042 "When forced to extrapolate T & S to match the layer "//&
4043 "densities, this factor (in deg C / PSU) is combined "//&
4044 "with the derivatives of density with T & S to determine "//&
4045 "what direction is orthogonal to density contours. It "//&
4046 "should be a typical value of (dR/dS) / (dR/dT) in oceanic profiles.", &
40471 units="degC ppt-1", default=6.0, scale=US%degC_to_C*US%S_to_ppt)
4048 call get_param(param_file, mdl, "BUFFER_LAYER_EXTRAP_LIMIT", CS%BL_extrap_lim, &
4049 "A limit on the density range over which extrapolation "//&
4050 "can occur when detraining from the buffer layers, "//&
4051 "relative to the density range within the mixed and "//&
4052 "buffer layers, when the detrainment is going into the "//&
4053 "lightest interior layer, nondimensional, or a negative "//&
40541 "value not to apply this limit.", units="nondim", default=-1.0)
4055 call get_param(param_file, mdl, "BUFFER_LAYER_HMIN_THICK", CS%Hbuffer_min, &
4056 "The minimum buffer layer thickness when the mixed layer is very thick.", &
40571 units="m", default=5.0, scale=GV%m_to_H)
4058 call get_param(param_file, mdl, "BUFFER_LAYER_HMIN_REL", CS%Hbuffer_rel_min, &
4059 "The minimum buffer layer thickness relative to the combined mixed "//&
4060 "land buffer ayer thicknesses when they are thin.", &
40611 units="nondim", default=0.1/CS%nkbl)
40621 if (CS%nkbl==1) then
4063 call get_param(param_file, mdl, "BUFFER_LAY_DETRAIN_TIME", CS%BL_detrain_time, &
4064 "A timescale that characterizes buffer layer detrainment events.", &
40650 units="s", default=86400.0*30.0, scale=US%s_to_T)
4066 else
4067 call get_param(param_file, mdl, "BUFFER_LAY_DETRAIN_TIME", CS%BL_detrain_time, &
4068 "A timescale that characterizes buffer layer detrainment events.", &
40691 units="s", default=4.0*3600.0, scale=US%s_to_T)
4070 endif
4071 call get_param(param_file, mdl, "BUFFER_SPLIT_RHO_TOL", CS%BL_split_rho_tol, &
4072 "The fractional tolerance for matching layer target densities when splitting "//&
4073 "layers to deal with massive interior layers that are lighter than one of the "//&
40741 "mixed or buffer layers.", units="nondim", default=0.1)
4075
4076 call get_param(param_file, mdl, "DEPTH_LIMIT_FLUXES", CS%H_limit_fluxes, &
4077 "The surface fluxes are scaled away when the total ocean "//&
4078 "depth is less than DEPTH_LIMIT_FLUXES.", &
40791 units="m", default=0.1*US%Z_to_m*Hmix_min_z, scale=GV%m_to_H)
4080 call get_param(param_file, mdl, "OMEGA", CS%omega, &
4081 "The rotation rate of the earth.", &
40821 default=7.2921e-5, units="s-1", scale=US%T_to_s)
4083 call get_param(param_file, mdl, "ML_USE_OMEGA", use_omega, &
4084 "If true, use the absolute rotation rate instead of the "//&
4085 "vertical component of rotation when setting the decay "//&
40861 "scale for turbulence.", default=.false., do_not_log=.true.)
40871 omega_frac_dflt = 0.0
40881 if (use_omega) then
40890 call MOM_error(WARNING, "ML_USE_OMEGA is depricated; use ML_OMEGA_FRAC=1.0 instead.")
40900 omega_frac_dflt = 1.0
4091 endif
4092 call get_param(param_file, mdl, "ML_OMEGA_FRAC", CS%omega_frac, &
4093 "When setting the decay scale for turbulence, use this "//&
4094 "fraction of the absolute rotation rate blended with the "//&
4095 "local value of f, as sqrt((1-of)*f^2 + of*4*omega^2).", &
40961 units="nondim", default=omega_frac_dflt)
4097 call get_param(param_file, mdl, "ML_RESORT", CS%ML_resort, &
4098 "If true, resort the topmost layers by potential density "//&
40991 "before the mixed layer calculations.", default=.false.)
41001 if (CS%ML_resort) &
4101 call get_param(param_file, mdl, "ML_PRESORT_NK_CONV_ADJ", CS%ML_presort_nz_conv_adj, &
4102 "Convectively mix the first ML_PRESORT_NK_CONV_ADJ "//&
4103 "layers before sorting when ML_RESORT is true.", &
41040 units="nondim", default=0, fail_if_missing=.true.) ! Fail added by AJA.
4105 ! This gives a minimum decay scale that is typically much less than Angstrom.
41061 ustar_min_dflt = 2e-4*CS%omega*(GV%Angstrom_Z + GV%dZ_subroundoff)
4107 call get_param(param_file, mdl, "BML_USTAR_MIN", CS%ustar_min, &
4108 "The minimum value of ustar that should be used by the "//&
4109 "bulk mixed layer model in setting vertical TKE decay "//&
4110 "scales. This must be greater than 0.", &
41111 units="m s-1", default=US%Z_to_m*US%s_to_T*ustar_min_dflt, scale=US%m_to_Z*US%T_to_s)
41121 if (CS%ustar_min<=0.0) call MOM_error(FATAL, "BML_USTAR_MIN must be positive.")
4113
4114 call get_param(param_file, mdl, "BML_NONBOUSINESQ", CS%nonBous_energetics, &
4115 "If true, use non-Boussinesq expressions for the energetic calculations "//&
4116 "used in the bulk mixed layer calculations.", &
41171 default=.not.(GV%Boussinesq.or.GV%semi_Boussinesq))
4118
4119 call get_param(param_file, mdl, "RESOLVE_EKMAN", CS%Resolve_Ekman, &
4120 "If true, the NKML>1 layers in the mixed layer are "//&
4121 "chosen to optimally represent the impact of the Ekman "//&
4122 "transport on the mixed layer TKE budget. Otherwise, "//&
4123 "the sublayers are distributed uniformly through the "//&
41241 "mixed layer.", default=.false.)
4125 call get_param(param_file, mdl, "CORRECT_ABSORPTION_DEPTH", CS%correct_absorption, &
4126 "If true, the average depth at which penetrating shortwave "//&
4127 "radiation is absorbed is adjusted to match the average "//&
4128 "heating depth of an exponential profile by moving some "//&
41291 "of the heating upward in the water column.", default=.false.)
4130 call get_param(param_file, mdl, "DO_RIVERMIX", CS%do_rivermix, &
4131 "If true, apply additional mixing wherever there is "//&
4132 "runoff, so that it is mixed down to RIVERMIX_DEPTH, "//&
41331 "if the ocean is that deep.", default=.false.)
41341 if (CS%do_rivermix) &
4135 call get_param(param_file, mdl, "RIVERMIX_DEPTH", CS%rivermix_depth, &
4136 "The depth to which rivers are mixed if DO_RIVERMIX is "//&
41370 "defined.", units="m", default=0.0, scale=GV%m_to_H)
4138 call get_param(param_file, mdl, "USE_RIVER_HEAT_CONTENT", CS%use_river_heat_content, &
4139 "If true, use the fluxes%runoff_Hflx field to set the "//&
4140 "heat carried by runoff, instead of using SST*CP*liq_runoff.", &
41411 default=.false.)
4142 call get_param(param_file, mdl, "USE_CALVING_HEAT_CONTENT", CS%use_calving_heat_content, &
4143 "If true, use the fluxes%calving_Hflx field to set the "//&
4144 "heat carried by runoff, instead of using SST*CP*froz_runoff.", &
41451 default=.false.)
4146 call get_param(param_file, mdl, "BULKML_CONV_MOMENTUM_BUG", CS%convect_mom_bug, &
4147 "If true, use code with a bug that causes a loss of momentum conservation "//&
41481 "during mixedlayer convection.", default=.false.)
4149
4150 CS%id_ML_depth = register_diag_field('ocean_model', 'h_ML', diag%axesT1, &
41511 Time, 'Surface mixed layer depth', 'm', conversion=GV%H_to_m)
4152 CS%id_TKE_wind = register_diag_field('ocean_model', 'TKE_wind', diag%axesT1, &
4153 Time, 'Wind-stirring source of mixed layer TKE', &
41541 'm3 s-3', conversion=GV%H_to_m*(US%Z_to_m**2)*(US%s_to_T**3))
4155 CS%id_TKE_RiBulk = register_diag_field('ocean_model', 'TKE_RiBulk', diag%axesT1, &
4156 Time, 'Mean kinetic energy source of mixed layer TKE', &
41571 'm3 s-3', conversion=GV%H_to_m*(US%Z_to_m**2)*(US%s_to_T**3))
4158 CS%id_TKE_conv = register_diag_field('ocean_model', 'TKE_conv', diag%axesT1, &
4159 Time, 'Convective source of mixed layer TKE', &
41601 'm3 s-3', conversion=GV%H_to_m*(US%Z_to_m**2)*(US%s_to_T**3))
4161 CS%id_TKE_pen_SW = register_diag_field('ocean_model', 'TKE_pen_SW', diag%axesT1, &
4162 Time, 'TKE consumed by mixing penetrative shortwave radation through the mixed layer', &
41631 'm3 s-3', conversion=GV%H_to_m*(US%Z_to_m**2)*(US%s_to_T**3))
4164 CS%id_TKE_mixing = register_diag_field('ocean_model', 'TKE_mixing', diag%axesT1, &
4165 Time, 'TKE consumed by mixing that deepens the mixed layer', &
41661 'm3 s-3', conversion=GV%H_to_m*(US%Z_to_m**2)*(US%s_to_T**3))
4167 CS%id_TKE_mech_decay = register_diag_field('ocean_model', 'TKE_mech_decay', diag%axesT1, &
4168 Time, 'Mechanical energy decay sink of mixed layer TKE', &
41691 'm3 s-3', conversion=GV%H_to_m*(US%Z_to_m**2)*(US%s_to_T**3))
4170 CS%id_TKE_conv_decay = register_diag_field('ocean_model', 'TKE_conv_decay', diag%axesT1, &
4171 Time, 'Convective energy decay sink of mixed layer TKE', &
41721 'm3 s-3', conversion=GV%H_to_m*(US%Z_to_m**2)*(US%s_to_T**3))
4173 CS%id_TKE_conv_s2 = register_diag_field('ocean_model', 'TKE_conv_s2', diag%axesT1, &
4174 Time, 'Spurious source of mixed layer TKE from sigma2', &
41751 'm3 s-3', conversion=GV%H_to_m*(US%Z_to_m**2)*(US%s_to_T**3))
4176 CS%id_PE_detrain = register_diag_field('ocean_model', 'PE_detrain', diag%axesT1, &
4177 Time, 'Spurious source of potential energy from mixed layer detrainment', &
41781 'W m-2', conversion=US%RZ3_T3_to_W_m2)
4179 CS%id_PE_detrain2 = register_diag_field('ocean_model', 'PE_detrain2', diag%axesT1, &
4180 Time, 'Spurious source of potential energy from mixed layer only detrainment', &
41811 'W m-2', conversion=US%RZ3_T3_to_W_m2)
4182 CS%id_h_mismatch = register_diag_field('ocean_model', 'h_miss_ML', diag%axesT1, &
41831 Time, 'Summed absolute mismatch in entrainment terms', 'm', conversion=GV%H_to_m)
4184 CS%id_Hsfc_used = register_diag_field('ocean_model', 'Hs_used', diag%axesT1, &
41851 Time, 'Surface region thickness that is used', 'm', conversion=GV%H_to_m)
4186 CS%id_Hsfc_max = register_diag_field('ocean_model', 'Hs_max', diag%axesT1, &
41871 Time, 'Maximum surface region thickness', 'm', conversion=GV%H_to_m)
4188 CS%id_Hsfc_min = register_diag_field('ocean_model', 'Hs_min', diag%axesT1, &
41891 Time, 'Minimum surface region thickness', 'm', conversion=GV%H_to_m)
4190 !CS%lim_det_dH_sfc = 0.5 ; CS%lim_det_dH_bathy = 0.2 ! Technically these should not get used if limit_det is false?
41911 if (CS%limit_det .or. (CS%id_Hsfc_min > 0)) then
4192 call get_param(param_file, mdl, "LIMIT_BUFFER_DET_DH_SFC", CS%lim_det_dH_sfc, &
4193 "The fractional limit in the change between grid points "//&
4194 "of the surface region (mixed & buffer layer) thickness.", &
41951 units="nondim", default=0.5)
4196 call get_param(param_file, mdl, "LIMIT_BUFFER_DET_DH_BATHY", CS%lim_det_dH_bathy, &
4197 "The fraction of the total depth by which the thickness "//&
4198 "of the surface region (mixed & buffer layer) is allowed "//&
41991 "to change between grid points.", units="nondim", default=0.2)
4200 endif
4201
4202 call get_param(param_file, mdl, "ENABLE_THERMODYNAMICS", use_temperature, &
4203 "If true, temperature and salinity are used as state "//&
42041 "variables.", default=.true.)
42051 CS%nsw = 0
42061 if (use_temperature) then
42071 call get_param(param_file, mdl, "PEN_SW_NBANDS", CS%nsw, default=1)
4208 endif
4209
4210
42111 if (max(CS%id_TKE_wind, CS%id_TKE_RiBulk, CS%id_TKE_conv, CS%id_TKE_mixing, &
4212 CS%id_TKE_pen_SW, CS%id_TKE_mech_decay, CS%id_TKE_conv_decay) > 0) then
42130 call safe_alloc_alloc(CS%diag_TKE_wind, isd, ied, jsd, jed)
42140 call safe_alloc_alloc(CS%diag_TKE_RiBulk, isd, ied, jsd, jed)
42150 call safe_alloc_alloc(CS%diag_TKE_conv, isd, ied, jsd, jed)
42160 call safe_alloc_alloc(CS%diag_TKE_pen_SW, isd, ied, jsd, jed)
42170 call safe_alloc_alloc(CS%diag_TKE_mixing, isd, ied, jsd, jed)
42180 call safe_alloc_alloc(CS%diag_TKE_mech_decay, isd, ied, jsd, jed)
42190 call safe_alloc_alloc(CS%diag_TKE_conv_decay, isd, ied, jsd, jed)
42200 call safe_alloc_alloc(CS%diag_TKE_conv_s2, isd, ied, jsd, jed)
4221
42220 CS%TKE_diagnostics = .true.
4223 endif
42241 if (CS%id_PE_detrain > 0) call safe_alloc_alloc(CS%diag_PE_detrain, isd, ied, jsd, jed)
42251 if (CS%id_PE_detrain2 > 0) call safe_alloc_alloc(CS%diag_PE_detrain2, isd, ied, jsd, jed)
42261 if (CS%id_ML_depth > 0) call safe_alloc_alloc(CS%ML_depth, isd, ied, jsd, jed)
4227
42281 if (CS%limit_det .or. (CS%id_Hsfc_min > 0)) &
42291 id_clock_pass = cpu_clock_id('(Ocean mixed layer halo updates)', grain=CLOCK_ROUTINE)
4230
4231end subroutine bulkmixedlayer_init
4232
4233!> This subroutine returns an approximation to the integral
4234!! R = exp(-L*(H+E)) integral(LH to L(H+E)) L/(1-(1+x)exp(-x)) dx.
4235!! The approximation to the integrand is good to within -2% at x~.3
4236!! and +25% at x~3.5, but the exponential deemphasizes the importance of
4237!! large x. When L=0, EF4 returns E/((Ht+E)*Ht).
4238457999function EF4(Ht, En, I_L, dR_de)
4239 real, intent(in) :: Ht !< Total thickness [H ~> m or kg m-2].
4240 real, intent(in) :: En !< Entrainment [H ~> m or kg m-2].
4241 real, intent(in) :: I_L !< The e-folding scale [H-1 ~> m-1 or m2 kg-1]
4242 real, optional, intent(inout) :: dR_de !< The partial derivative of the result R with E [H-2 ~> m-2 or m4 kg-2].
4243 real :: EF4 !< The integral [H-1 ~> m-1 or m2 kg-1].
4244
4245 ! Local variables
4246 real :: exp_LHpE ! A nondimensional exponential decay [nondim].
4247 real :: I_HpE ! An inverse thickness plus entrainment [H-1 ~> m-1 or m2 kg-1].
4248 real :: Res ! The result of the integral above [H-1 ~> m-1 or m2 kg-1].
4249
4250457999 exp_LHpE = exp(-I_L*(En+Ht))
4251457999 I_HpE = 1.0/(Ht+En)
4252457999 Res = exp_LHpE * (En*I_HpE/Ht - 0.5*I_L*log(Ht*I_HpE) + 0.5*I_L*I_L*En)
4253457999 if (PRESENT(dR_de)) &
4254330432 dR_de = -I_L*Res + exp_LHpE*(I_HpE*I_HpE + 0.5*I_L*I_HpE + 0.5*I_L*I_L)
4255457999 EF4 = Res
4256
4257457999end function EF4
4258
4259!> \namespace mom_bulk_mixed_layer
4260!!
4261!! By Robert Hallberg, 1997 - 2005.
4262!!
4263!! This file contains the subroutine (bulkmixedlayer) that
4264!! implements a Kraus-Turner-like bulk mixed layer, based on the work
4265!! of various people, as described in the review paper by \cite niiler1977,
4266!! with particular attention to the form proposed by \cite Oberhuber1993a,
4267!! with an extension to a refined bulk mixed layer as described in
4268!! Hallberg (\cite muller2003). The physical processes portrayed in
4269!! this subroutine include convective adjustment and mixed layer entrainment
4270!! and detrainment. Penetrating shortwave radiation and an exponential decay
4271!! of TKE fluxes are also supported by this subroutine. Several constants
4272!! can alternately be set to give a traditional Kraus-Turner mixed
4273!! layer scheme, although that is not the preferred option. The
4274!! physical processes and arguments are described in detail in \ref BML.
4275
42760end module MOM_bulk_mixed_layer