MOM6
mom_tracer_diabatic Module Reference

Detailed Description

This module contains routines that implement physical fluxes of tracers (e.g. due to surface fluxes or mixing). These are intended to be called from call_tracer_column_fns in the MOM_tracer_flow_control module.

Functions/Subroutines

subroutine, public tracer_vertdiff (h_old, ea, eb, dt, tr, G, GV, sfc_flux, btm_flux, btm_reservoir, sink_rate, convert_flux_in)
 This subroutine solves a tridiagonal equation for the final tracer concentrations after the dual-entrainments, and possibly sinking or surface and bottom sources, are applied. The sinking is implemented with an fully implicit upwind advection scheme. More...
 
subroutine, public applytracerboundaryfluxesinout (G, GV, Tr, dt, fluxes, h, evap_CFL_limit, minimum_forcing_depth, in_flux_optional, out_flux_optional, update_h_opt)
 This routine is modeled after applyBoundaryFluxesInOut in MOM_diabatic_aux.F90 NOTE: Please note that in this routine sfc_flux gets set to zero to ensure that the surface flux of the tracer does not get applied again during a subsequent call to tracer_vertdif. More...
 

Function/Subroutine Documentation

◆ applytracerboundaryfluxesinout()

subroutine, public mom_tracer_diabatic::applytracerboundaryfluxesinout ( type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
real, dimension(szi_(g),szj_(g),szk_(g)), intent(inout)  Tr,
real, intent(in)  dt,
type(forcing), intent(in)  fluxes,
real, dimension(szi_(g),szj_(g),szk_(g)), intent(inout)  h,
real, intent(in)  evap_CFL_limit,
real, intent(in)  minimum_forcing_depth,
real, dimension(szi_(g),szj_(g)), intent(in), optional  in_flux_optional,
real, dimension(szi_(g),szj_(g)), intent(in), optional  out_flux_optional,
logical, intent(in), optional  update_h_opt 
)

This routine is modeled after applyBoundaryFluxesInOut in MOM_diabatic_aux.F90 NOTE: Please note that in this routine sfc_flux gets set to zero to ensure that the surface flux of the tracer does not get applied again during a subsequent call to tracer_vertdif.

Parameters
[in]gGrid structure
[in]gvocean vertical grid structure
[in,out]trTracer concentration on T-cell
[in]dtTime-step over which forcing is applied [s]
[in]fluxesSurface fluxes container
[in,out]hLayer thickness [H ~> m or kg m-2]
[in]evap_cfl_limitLimit on the fraction of the water that can be fluxed out of the top layer in a timestep [nondim]
[in]minimum_forcing_depthThe smallest depth over which fluxes can be applied [m]
[in]in_flux_optionalThe total time-integrated amount of tracer that enters with freshwater
[in]out_flux_optionalThe total time-integrated amount of tracer that leaves with freshwater
[in]update_h_optOptional flag to determine whether h should be updated

Definition at line 225 of file MOM_tracer_diabatic.F90.

225 
226  type(ocean_grid_type), intent(in ) :: G !< Grid structure
227  type(verticalGrid_type), intent(in ) :: GV !< ocean vertical grid structure
228  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: Tr !< Tracer concentration on T-cell
229  real, intent(in ) :: dt !< Time-step over which forcing is applied [s]
230  type(forcing), intent(in ) :: fluxes !< Surface fluxes container
231  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(inout) :: h !< Layer thickness [H ~> m or kg m-2]
232  real, intent(in ) :: evap_CFL_limit !< Limit on the fraction of the
233  !! water that can be fluxed out of the top
234  !! layer in a timestep [nondim]
235  real, intent(in ) :: minimum_forcing_depth !< The smallest depth over
236  !! which fluxes can be applied [m]
237  real, dimension(SZI_(G),SZJ_(G)), optional, intent(in ) :: in_flux_optional !< The total time-integrated
238  !! amount of tracer that enters with freshwater
239  real, dimension(SZI_(G),SZJ_(G)), optional, intent(in) :: out_flux_optional !< The total time-integrated
240  !! amount of tracer that leaves with freshwater
241  logical, optional, intent(in) :: update_h_opt !< Optional flag to determine whether
242  !! h should be updated
243 
244  integer, parameter :: maxGroundings = 5
245  integer :: numberOfGroundings, iGround(maxGroundings), jGround(maxGroundings)
246  real :: H_limit_fluxes, IforcingDepthScale, Idt
247  real :: dThickness, dTracer
248  real :: fractionOfForcing, hOld, Ithickness
249  real :: RivermixConst ! A constant used in implementing river mixing [Pa s].
250  real, dimension(SZI_(G)) :: &
251  netMassInOut, & ! surface water fluxes [H ~> m or kg m-2] over time step
252  netMassIn, & ! mass entering ocean surface [H ~> m or kg m-2] over a time step
253  netMassOut ! mass leaving ocean surface [H ~> m or kg m-2] over a time step
254 
255  real, dimension(SZI_(G), SZK_(G)) :: h2d, Tr2d
256  real, dimension(SZI_(G),SZJ_(G)) :: in_flux ! The total time-integrated amount of tracer!
257  ! that enters with freshwater
258  real, dimension(SZI_(G),SZJ_(G)) :: out_flux ! The total time-integrated amount of tracer!
259  ! that leaves with freshwater
260  real, dimension(SZI_(G)) :: in_flux_1d, out_flux_1d
261  real :: hGrounding(maxGroundings)
262  real :: Tr_in
263  logical :: update_h
264  integer :: i, j, is, ie, js, je, k, nz, n, nsw
265  character(len=45) :: mesg
266 
267  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
268 
269  ! If no freshwater fluxes, nothing needs to be done in this routine
270  if ( (.not. associated(fluxes%netMassIn)) .or. (.not. associated(fluxes%netMassOut)) ) return
271 
272  in_flux(:,:) = 0.0 ; out_flux(:,:) = 0.0
273  if (present(in_flux_optional)) then
274  do j=js,je ; do i=is,ie
275  in_flux(i,j) = in_flux_optional(i,j)
276  enddo ; enddo
277  endif
278  if (present(out_flux_optional)) then
279  do j=js,je ; do i=is,ie
280  out_flux(i,j) = out_flux_optional(i,j)
281  enddo ; enddo
282  endif
283 
284  if (present(update_h_opt)) then
285  update_h = update_h_opt
286  else
287  update_h = .true.
288  endif
289 
290  idt = 1.0/dt
291  numberofgroundings = 0
292 
293 !$OMP parallel do default(none) shared(is,ie,js,je,nz,h,Tr,G,GV,fluxes,dt, &
294 !$OMP IforcingDepthScale,minimum_forcing_depth, &
295 !$OMP numberOfGroundings,iGround,jGround,update_h, &
296 !$OMP in_flux,out_flux,hGrounding,Idt,evap_CFL_limit) &
297 !$OMP private(h2d,Tr2d,netMassInOut,netMassOut, &
298 !$OMP in_flux_1d,out_flux_1d,fractionOfForcing, &
299 !$OMP dThickness,dTracer,hOld,Ithickness, &
300 !$OMP netMassIn, Tr_in)
301 
302  ! Work in vertical slices for efficiency
303  do j=js,je
304 
305  ! Copy state into 2D-slice arrays
306  do k=1,nz ; do i=is,ie
307  h2d(i,k) = h(i,j,k)
308  tr2d(i,k) = tr(i,j,k)
309  enddo ; enddo
310 
311  do i = is,ie
312  in_flux_1d(i) = in_flux(i,j)
313  out_flux_1d(i) = out_flux(i,j)
314  enddo
315  ! The surface forcing is contained in the fluxes type.
316  ! We aggregate the thermodynamic forcing for a time step into the following:
317  ! These should have been set and stored during a call to applyBoundaryFluxesInOut
318  ! netMassIn = net mass entering at ocean surface over a timestep
319  ! netMassOut = net mass leaving ocean surface [H ~> m or kg m-2] over a time step.
320  ! netMassOut < 0 means mass leaves ocean.
321 
322  ! Note here that the aggregateFW flag has already been taken care of in the call to
323  ! applyBoundaryFluxesInOut
324  do i=is,ie
325  netmassout(i) = fluxes%netMassOut(i,j)
326  netmassin(i) = fluxes%netMassIn(i,j)
327  enddo
328 
329  ! Apply the surface boundary fluxes in three steps:
330  ! A/ update concentration from mass entering the ocean
331  ! B/ update concentration from mass leaving ocean.
332  do i=is,ie
333  if (g%mask2dT(i,j)>0.) then
334 
335  ! A/ Update tracer due to incoming mass flux.
336  do k=1,1
337 
338  ! Change in state due to forcing
339  dthickness = netmassin(i) ! Since we are adding mass, we can use all of it
340  dtracer = 0.
341 
342  ! Update the forcing by the part to be consumed within the present k-layer.
343  ! If fractionOfForcing = 1, then updated netMassIn, netHeat, and netSalt vanish.
344  netmassin(i) = netmassin(i) - dthickness
345  dtracer = dtracer + in_flux_1d(i)
346  in_flux_1d(i) = 0.0
347 
348  ! Update state
349  hold = h2d(i,k) ! Keep original thickness in hand
350  h2d(i,k) = h2d(i,k) + dthickness ! New thickness
351  if (h2d(i,k) > 0.0) then
352  ithickness = 1.0/h2d(i,k) ! Inverse new thickness
353  ! The "if"s below avoid changing T/S by roundoff unnecessarily
354  if (dthickness /= 0. .or. dtracer /= 0.) tr2d(i,k) = (hold*tr2d(i,k)+ dtracer)*ithickness
355  endif
356 
357  enddo ! k=1,1
358 
359  ! B/ Update tracer from mass leaving ocean
360  do k=1,nz
361 
362  ! Place forcing into this layer if this layer has nontrivial thickness.
363  ! For layers thin relative to 1/IforcingDepthScale, then distribute
364  ! forcing into deeper layers.
365  iforcingdepthscale = 1. / max(gv%H_subroundoff, minimum_forcing_depth*gv%m_to_H - netmassout(i) )
366  ! fractionOfForcing = 1.0, unless h2d is less than IforcingDepthScale.
367  fractionofforcing = min(1.0, h2d(i,k)*iforcingdepthscale)
368 
369  ! In the case with (-1)*netMassOut*fractionOfForcing greater than cfl*h, we
370  ! limit the forcing applied to this cell, leaving the remaining forcing to
371  ! be distributed downwards.
372  if (-fractionofforcing*netmassout(i) > evap_cfl_limit*h2d(i,k)) then
373  fractionofforcing = -evap_cfl_limit*h2d(i,k)/netmassout(i)
374  endif
375 
376  ! Change in state due to forcing
377  dthickness = max( fractionofforcing*netmassout(i), -h2d(i,k) )
378  ! Note this is slightly different to how salt is currently treated
379  dtracer = fractionofforcing*out_flux_1d(i)
380 
381  ! Update the forcing by the part to be consumed within the present k-layer.
382  ! If fractionOfForcing = 1, then new netMassOut vanishes.
383  netmassout(i) = netmassout(i) - dthickness
384  out_flux_1d(i) = out_flux_1d(i) - dtracer
385 
386  ! Update state by the appropriate increment.
387  hold = h2d(i,k) ! Keep original thickness in hand
388  h2d(i,k) = h2d(i,k) + dthickness ! New thickness
389  if (h2d(i,k) > 0.) then
390  ithickness = 1.0/h2d(i,k) ! Inverse of new thickness
391  tr2d(i,k) = (hold*tr2d(i,k) + dtracer)*ithickness
392  endif
393 
394  enddo ! k
395 
396  endif
397 
398  ! If anything remains after the k-loop, then we have grounded out, which is a problem.
399  if (abs(in_flux_1d(i))+abs(out_flux_1d(i)) /= 0.0) then
400 !$OMP critical
401  numberofgroundings = numberofgroundings +1
402  if (numberofgroundings<=maxgroundings) then
403  iground(numberofgroundings) = i ! Record i,j location of event for
404  jground(numberofgroundings) = j ! warning message
405  hgrounding(numberofgroundings) = abs(in_flux_1d(i))+abs(out_flux_1d(i))
406  endif
407 !$OMP end critical
408  endif
409 
410  enddo ! i
411 
412  ! Step C/ copy updated tracer concentration from the 2d slice now back into model state.
413  do k=1,nz ; do i=is,ie
414  tr(i,j,k) = tr2d(i,k)
415  enddo ; enddo
416 
417  if (update_h) then
418  do k=1,nz ; do i=is,ie
419  h(i,j,k) = h2d(i,k)
420  enddo ; enddo
421  endif
422 
423  enddo ! j-loop finish
424 
425  if (numberofgroundings>0) then
426  do i = 1, min(numberofgroundings, maxgroundings)
427  write(mesg(1:45),'(3es15.3)') g%geoLonT( iground(i), jground(i) ), &
428  g%geoLatT( iground(i), jground(i)) , hgrounding(i)
429  call mom_error(warning, "MOM_tracer_diabatic.F90, applyTracerBoundaryFluxesInOut(): "//&
430  "Tracer created. x,y,dh= "//trim(mesg), all_print=.true.)
431  enddo
432 
433  if (numberofgroundings - maxgroundings > 0) then
434  write(mesg, '(i4)') numberofgroundings - maxgroundings
435  call mom_error(warning, "MOM_tracer_vertical.F90, applyTracerBoundaryFluxesInOut(): "//&
436  trim(mesg) // " groundings remaining")
437  endif
438  endif
439 

◆ tracer_vertdiff()

subroutine, public mom_tracer_diabatic::tracer_vertdiff ( real, dimension( g %isd: g %ied, g %jsd: g %jed, gv %ke), intent(in)  h_old,
real, dimension( g %isd: g %ied, g %jsd: g %jed, gv %ke), intent(in)  ea,
real, dimension( g %isd: g %ied, g %jsd: g %jed, gv %ke), intent(in)  eb,
real, intent(in)  dt,
real, dimension( g %isd: g %ied, g %jsd: g %jed, gv %ke), intent(inout)  tr,
type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
real, dimension( g %isd: g %ied, g %jsd: g %jed), intent(in), optional  sfc_flux,
real, dimension( g %isd: g %ied, g %jsd: g %jed), intent(in), optional  btm_flux,
real, dimension( g %isd: g %ied, g %jsd: g %jed), intent(inout), optional  btm_reservoir,
real, intent(in), optional  sink_rate,
logical, intent(in), optional  convert_flux_in 
)

This subroutine solves a tridiagonal equation for the final tracer concentrations after the dual-entrainments, and possibly sinking or surface and bottom sources, are applied. The sinking is implemented with an fully implicit upwind advection scheme.

Parameters
[in]gocean grid structure
[in]gvocean vertical grid structure
[in]h_oldlayer thickness before entrainment [H ~> m or kg m-2]
[in]eaamount of fluid entrained from the layer above [H ~> m or kg m-2]
[in]ebamount of fluid entrained from the layer below [H ~> m or kg m-2]
[in,out]trtracer concentration in concentration units [CU]
[in]dtamount of time covered by this call [s]
[in]sfc_fluxsurface flux of the tracer [CU kg m-2 s-1]
[in]btm_fluxThe (negative upward) bottom flux of the tracer [CU kg m-2 s-1]
[in,out]btm_reservoiramount of tracer in a bottom reservoir [CU kg m-2]; formerly [CU m]
[in]sink_raterate at which the tracer sinks [m s-1]
[in]convert_flux_inTrue if the specified sfc_flux needs to be integrated in time

Definition at line 27 of file MOM_tracer_diabatic.F90.

27  type(ocean_grid_type), intent(in) :: G !< ocean grid structure
28  type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure
29  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h_old !< layer thickness before entrainment
30  !! [H ~> m or kg m-2]
31  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: ea !< amount of fluid entrained from the layer
32  !! above [H ~> m or kg m-2]
33  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: eb !< amount of fluid entrained from the layer
34  !! below [H ~> m or kg m-2]
35  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(inout) :: tr !< tracer concentration in concentration units [CU]
36  real, intent(in) :: dt !< amount of time covered by this call [s]
37  real, dimension(SZI_(G),SZJ_(G)), optional,intent(in) :: sfc_flux !< surface flux of the tracer [CU kg m-2 s-1]
38  real, dimension(SZI_(G),SZJ_(G)), optional,intent(in) :: btm_flux !< The (negative upward) bottom flux of the
39  !! tracer [CU kg m-2 s-1]
40  real, dimension(SZI_(G),SZJ_(G)), optional,intent(inout) :: btm_reservoir !< amount of tracer in a bottom reservoir
41  !! [CU kg m-2]; formerly [CU m]
42  real, optional,intent(in) :: sink_rate !< rate at which the tracer sinks [m s-1]
43  logical, optional,intent(in) :: convert_flux_in !< True if the specified sfc_flux needs
44  !! to be integrated in time
45 
46  ! local variables
47  real :: sink_dist !< The distance the tracer sinks in a time step [H ~> m or kg m-2].
48  real, dimension(SZI_(G),SZJ_(G)) :: &
49  sfc_src, & !< The time-integrated surface source of the tracer [CU H ~> CU m or CU kg m-2].
50  btm_src !< The time-integrated bottom source of the tracer [CU H ~> CU m or CU kg m-2].
51  real, dimension(SZI_(G)) :: &
52  b1, & !< b1 is used by the tridiagonal solver [H-1 ~> m-1 or m2 kg-1].
53  d1 !! d1=1-c1 is used by the tridiagonal solver, nondimensional.
54  real :: c1(SZI_(G),SZK_(GV)) !< c1 is used by the tridiagonal solver [nondim].
55  real :: h_minus_dsink(SZI_(G),SZK_(GV)) !< The layer thickness minus the
56  !! difference in sinking rates across the layer [H ~> m or kg m-2].
57  !! By construction, 0 <= h_minus_dsink < h_work.
58  real :: sink(SZI_(G),SZK_(GV)+1) !< The tracer's sinking distances at the
59  !! interfaces, limited to prevent characteristics from
60  !! crossing within a single timestep [H ~> m or kg m-2].
61  real :: b_denom_1 !< The first term in the denominator of b1 [H ~> m or kg m-2].
62  real :: h_tr !< h_tr is h at tracer points with a h_neglect added to
63  !! ensure positive definiteness [H ~> m or kg m-2].
64  real :: h_neglect !< A thickness that is so small it is usually lost
65  !! in roundoff and can be neglected [H ~> m or kg m-2].
66  logical :: convert_flux = .true.
67 
68 
69  integer :: i, j, k, is, ie, js, je, nz
70  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
71 
72  if (nz == 1) then
73  call mom_error(warning, "MOM_tracer_diabatic.F90, tracer_vertdiff called "//&
74  "with only one vertical level")
75  return
76  endif
77 
78  if (present(convert_flux_in)) convert_flux = convert_flux_in
79  h_neglect = gv%H_subroundoff
80  sink_dist = 0.0
81  if (present(sink_rate)) sink_dist = (dt*sink_rate) * gv%m_to_H
82 !$OMP parallel default(none) shared(is,ie,js,je,sfc_src,btm_src,sfc_flux,dt,G,GV,btm_flux, &
83 !$OMP sink_rate,btm_reservoir,nz,sink_dist,ea, &
84 !$OMP h_old,convert_flux,h_neglect,eb,tr) &
85 !$OMP private(sink,h_minus_dsink,b_denom_1,b1,d1,h_tr,c1)
86 !$OMP do
87  do j=js,je; do i=is,ie ; sfc_src(i,j) = 0.0 ; btm_src(i,j) = 0.0 ; enddo ; enddo
88  if (present(sfc_flux)) then
89  if (convert_flux) then
90 !$OMP do
91  do j = js, je; do i = is,ie
92  sfc_src(i,j) = (sfc_flux(i,j)*dt) * gv%kg_m2_to_H
93  enddo ; enddo
94  else
95 !$OMP do
96  do j = js, je; do i = is,ie
97  sfc_src(i,j) = sfc_flux(i,j)
98  enddo ; enddo
99  endif
100  endif
101  if (present(btm_flux)) then
102  if (convert_flux) then
103 !$OMP do
104  do j = js, je; do i = is,ie
105  btm_src(i,j) = (btm_flux(i,j)*dt) * gv%kg_m2_to_H
106  enddo ; enddo
107  else
108 !$OMP do
109  do j = js, je; do i = is,ie
110  btm_src(i,j) = btm_flux(i,j)
111  enddo ; enddo
112  endif
113  endif
114 
115  if (present(sink_rate)) then
116 !$OMP do
117  do j=js,je
118  ! Find the sinking rates at all interfaces, limiting them if necesary
119  ! so that the characteristics do not cross within a timestep.
120  ! If a non-constant sinking rate were used, that would be incorprated
121  ! here.
122  if (present(btm_reservoir)) then
123  do i=is,ie ; sink(i,nz+1) = sink_dist ; enddo
124  do k=2,nz ; do i=is,ie
125  sink(i,k) = sink_dist ; h_minus_dsink(i,k) = h_old(i,j,k)
126  enddo ; enddo
127  else
128  do i=is,ie ; sink(i,nz+1) = 0.0 ; enddo
129  ! Find the limited sinking distance at the interfaces.
130  do k=nz,2,-1 ; do i=is,ie
131  if (sink(i,k+1) >= sink_dist) then
132  sink(i,k) = sink_dist
133  h_minus_dsink(i,k) = h_old(i,j,k) + (sink(i,k+1) - sink(i,k))
134  elseif (sink(i,k+1) + h_old(i,j,k) < sink_dist) then
135  sink(i,k) = sink(i,k+1) + h_old(i,j,k)
136  h_minus_dsink(i,k) = 0.0
137  else
138  sink(i,k) = sink_dist
139  h_minus_dsink(i,k) = (h_old(i,j,k) + sink(i,k+1)) - sink(i,k)
140  endif
141  enddo ; enddo
142  endif
143  do i=is,ie
144  sink(i,1) = 0.0 ; h_minus_dsink(i,1) = (h_old(i,j,1) + sink(i,2))
145  enddo
146 
147  ! Now solve the tridiagonal equation for the tracer concentrations.
148  do i=is,ie ; if (g%mask2dT(i,j) > 0.5) then
149  b_denom_1 = h_minus_dsink(i,1) + ea(i,j,1) + h_neglect
150  b1(i) = 1.0 / (b_denom_1 + eb(i,j,1))
151  d1(i) = b_denom_1 * b1(i)
152  h_tr = h_old(i,j,1) + h_neglect
153  tr(i,j,1) = (b1(i)*h_tr)*tr(i,j,1) + sfc_src(i,j)
154  endif ; enddo
155  do k=2,nz-1 ; do i=is,ie ; if (g%mask2dT(i,j) > 0.5) then
156  c1(i,k) = eb(i,j,k-1) * b1(i)
157  b_denom_1 = h_minus_dsink(i,k) + d1(i) * (ea(i,j,k) + sink(i,k)) + &
158  h_neglect
159  b1(i) = 1.0 / (b_denom_1 + eb(i,j,k))
160  d1(i) = b_denom_1 * b1(i)
161  h_tr = h_old(i,j,k) + h_neglect
162  tr(i,j,k) = b1(i) * (h_tr * tr(i,j,k) + &
163  (ea(i,j,k) + sink(i,k)) * tr(i,j,k-1))
164  endif ; enddo ; enddo
165  do i=is,ie ; if (g%mask2dT(i,j) > 0.5) then
166  c1(i,nz) = eb(i,j,nz-1) * b1(i)
167  b_denom_1 = h_minus_dsink(i,nz) + d1(i) * (ea(i,j,nz) + sink(i,nz)) + &
168  h_neglect
169  b1(i) = 1.0 / (b_denom_1 + eb(i,j,nz))
170  h_tr = h_old(i,j,nz) + h_neglect
171  tr(i,j,nz) = b1(i) * ((h_tr * tr(i,j,nz) + btm_src(i,j)) + &
172  (ea(i,j,nz) + sink(i,nz)) * tr(i,j,nz-1))
173  endif ; enddo
174  if (present(btm_reservoir)) then ; do i=is,ie ; if (g%mask2dT(i,j)>0.5) then
175  btm_reservoir(i,j) = btm_reservoir(i,j) + &
176  (sink(i,nz+1)*tr(i,j,nz)) * gv%H_to_kg_m2
177  endif ; enddo ; endif
178 
179  do k=nz-1,1,-1 ; do i=is,ie ; if (g%mask2dT(i,j) > 0.5) then
180  tr(i,j,k) = tr(i,j,k) + c1(i,k+1)*tr(i,j,k+1)
181  endif ; enddo ; enddo
182  enddo
183  else
184 !$OMP do
185  do j=js,je
186  do i=is,ie ; if (g%mask2dT(i,j) > -0.5) then
187  h_tr = h_old(i,j,1) + h_neglect
188  b_denom_1 = h_tr + ea(i,j,1)
189  b1(i) = 1.0 / (b_denom_1 + eb(i,j,1))
190  d1(i) = h_tr * b1(i)
191  tr(i,j,1) = (b1(i)*h_tr)*tr(i,j,1) + sfc_src(i,j)
192  endif
193  enddo
194  do k=2,nz-1 ; do i=is,ie ; if (g%mask2dT(i,j) > -0.5) then
195  c1(i,k) = eb(i,j,k-1) * b1(i)
196  h_tr = h_old(i,j,k) + h_neglect
197  b_denom_1 = h_tr + d1(i) * ea(i,j,k)
198  b1(i) = 1.0 / (b_denom_1 + eb(i,j,k))
199  d1(i) = b_denom_1 * b1(i)
200  tr(i,j,k) = b1(i) * (h_tr * tr(i,j,k) + ea(i,j,k) * tr(i,j,k-1))
201  endif ; enddo ; enddo
202  do i=is,ie ; if (g%mask2dT(i,j) > -0.5) then
203  c1(i,nz) = eb(i,j,nz-1) * b1(i)
204  h_tr = h_old(i,j,nz) + h_neglect
205  b_denom_1 = h_tr + d1(i)*ea(i,j,nz)
206  b1(i) = 1.0 / ( b_denom_1 + eb(i,j,nz))
207  tr(i,j,nz) = b1(i) * (( h_tr * tr(i,j,nz) + btm_src(i,j)) + &
208  ea(i,j,nz) * tr(i,j,nz-1))
209  endif ; enddo
210  do k=nz-1,1,-1 ; do i=is,ie ; if (g%mask2dT(i,j) > -0.5) then
211  tr(i,j,k) = tr(i,j,k) + c1(i,k+1)*tr(i,j,k+1)
212  endif ; enddo ; enddo
213  enddo
214  endif
215 
216 !$OMP end parallel
217