6 use mom_cpu_clock,
only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
10 use mom_domains,
only : sum_across_pes, max_across_pes
29 implicit none ;
private
31 #include <MOM_memory.h>
33 public tracer_hordiff, tracer_hor_diff_init, tracer_hor_diff_end
39 real :: khtr_slope_cff
42 real :: khtr_passivity_coeff
45 real :: khtr_passivity_min
52 logical :: diffuse_ml_interior
54 logical :: check_diffusive_cfl
57 logical :: use_neutral_diffusion
63 logical :: show_call_tree
64 logical :: first_call = .true.
66 integer :: id_khtr_u = -1
67 integer :: id_khtr_v = -1
68 integer :: id_khtr_h = -1
69 integer :: id_cfl = -1
70 integer :: id_khdt_x = -1
71 integer :: id_khdt_y = -1
74 type(group_pass_type) :: pass_t
80 real,
dimension(:,:),
pointer :: p => null()
84 integer,
dimension(:,:),
pointer :: p => null()
88 integer :: id_clock_diffuse, id_clock_epimix, id_clock_pass, id_clock_sync
97 subroutine tracer_hordiff(h, dt, MEKE, VarMix, G, GV, CS, Reg, tv, do_online_flag, read_khdt_x, read_khdt_y)
99 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
101 real,
intent(in) :: dt
114 logical,
optional,
intent(in) :: do_online_flag
116 real,
dimension(SZIB_(G),SZJ_(G)), &
117 optional,
intent(in) :: read_khdt_x
119 real,
dimension(SZI_(G),SZJB_(G)), &
120 optional,
intent(in) :: read_khdt_y
124 real,
dimension(SZI_(G),SZJ_(G)) :: &
131 real,
dimension(SZIB_(G),SZJ_(G)) :: &
137 real,
dimension(SZI_(G),SZJB_(G)) :: &
146 logical :: use_varmix, resoln_scaled, do_online, use_eady
147 integer :: s_idx, t_idx
148 integer :: i, j, k, m, is, ie, js, je, nz, ntr, itt, num_itts
160 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
163 if (
present(do_online_flag)) do_online = do_online_flag
165 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_tracer_hor_diff: "// &
166 "register_tracer must be called before tracer_hordiff.")
167 if (loc(reg)==0)
call mom_error(fatal,
"MOM_tracer_hor_diff: "// &
168 "register_tracer must be called before tracer_hordiff.")
169 if ((reg%ntr==0) .or. ((cs%KhTr <= 0.0) .and. .not.
associated(varmix)) )
return
171 if (cs%show_call_tree)
call calltree_enter(
"tracer_hordiff(), MOM_tracer_hor_diff.F90")
173 call cpu_clock_begin(id_clock_diffuse)
177 h_neglect = gv%H_subroundoff
179 if (cs%Diffuse_ML_interior .and. cs%first_call)
then ;
if (is_root_pe())
then
180 do m=1,ntr ;
if (
associated(reg%Tr(m)%df_x) .or.
associated(reg%Tr(m)%df_y)) &
181 call mom_error(warning,
"tracer_hordiff: Tracer "//trim(reg%Tr(m)%name)// &
182 " has associated 3-d diffusive flux diagnostics. These are not "//&
183 "valid when DIFFUSE_ML_TO_INTERIOR is defined. Use 2-d tracer "//&
184 "diffusion diagnostics instead to get accurate total fluxes.")
187 cs%first_call = .false.
189 if (cs%debug)
call mom_tracer_chksum(
"Before tracer diffusion ", reg%Tr, ntr, g)
191 use_varmix = .false. ; resoln_scaled = .false. ; use_eady = .false.
192 if (
Associated(varmix))
then
193 use_varmix = varmix%use_variable_mixing
194 resoln_scaled = varmix%Resoln_scaled_KhTr
195 use_eady = cs%KhTr_Slope_Cff > 0.
198 call cpu_clock_begin(id_clock_pass)
202 call cpu_clock_end(id_clock_pass)
204 if (cs%show_call_tree)
call calltree_waypoint(
"Calculating diffusivity (tracer_hordiff)")
209 do j=js,je ;
do i=is-1,ie
211 if (use_eady) kh_loc = kh_loc + cs%KhTr_Slope_Cff*varmix%L2u(i,j)*varmix%SN_u(i,j)
212 if (
associated(meke%Kh)) &
213 kh_loc = kh_loc + meke%KhTr_fac*sqrt(meke%Kh(i,j)*meke%Kh(i+1,j))
214 if (cs%KhTr_max > 0.) kh_loc = min(kh_loc, cs%KhTr_max)
216 kh_loc = kh_loc * 0.5*(varmix%Res_fn_h(i,j) + varmix%Res_fn_h(i+1,j))
217 kh_u(i,j) = max(kh_loc, cs%KhTr_min)
218 if (cs%KhTr_passivity_coeff>0.)
then
219 rd_dx=0.5*( varmix%Rd_dx_h(i,j)+varmix%Rd_dx_h(i+1,j) )
220 kh_loc=kh_u(i,j)*max( cs%KhTr_passivity_min, cs%KhTr_passivity_coeff*rd_dx )
221 if (cs%KhTr_max > 0.) kh_loc = min(kh_loc, cs%KhTr_max)
222 kh_u(i,j) = max(kh_loc, cs%KhTr_min)
226 do j=js-1,je ;
do i=is,ie
228 if (use_eady) kh_loc = kh_loc + cs%KhTr_Slope_Cff*varmix%L2v(i,j)*varmix%SN_v(i,j)
229 if (
associated(meke%Kh)) &
230 kh_loc = kh_loc + meke%KhTr_fac*sqrt(meke%Kh(i,j)*meke%Kh(i,j+1))
231 if (cs%KhTr_max > 0.) kh_loc = min(kh_loc, cs%KhTr_max)
233 kh_loc = kh_loc * 0.5*(varmix%Res_fn_h(i,j) + varmix%Res_fn_h(i,j+1))
234 kh_v(i,j) = max(kh_loc, cs%KhTr_min)
235 if (cs%KhTr_passivity_coeff>0.)
then
236 rd_dx=0.5*( varmix%Rd_dx_h(i,j)+varmix%Rd_dx_h(i,j+1) )
237 kh_loc=kh_v(i,j)*max( cs%KhTr_passivity_min, cs%KhTr_passivity_coeff*rd_dx )
238 if (cs%KhTr_max > 0.) kh_loc = min(kh_loc, cs%KhTr_max)
239 kh_v(i,j) = max(kh_loc, cs%KhTr_min)
244 do j=js,je ;
do i=is-1,ie
245 khdt_x(i,j) = dt*(kh_u(i,j)*(g%dy_Cu(i,j)*g%IdxCu(i,j)))
248 do j=js-1,je ;
do i=is,ie
249 khdt_y(i,j) = dt*(kh_v(i,j)*(g%dx_Cv(i,j)*g%IdyCv(i,j)))
251 elseif (resoln_scaled)
then
253 do j=js,je ;
do i=is-1,ie
254 res_fn = 0.5 * (varmix%Res_fn_h(i,j) + varmix%Res_fn_h(i+1,j))
255 kh_u(i,j) = max(cs%KhTr * res_fn, cs%KhTr_min)
256 khdt_x(i,j) = dt*(cs%KhTr*(g%dy_Cu(i,j)*g%IdxCu(i,j))) * res_fn
259 do j=js-1,je ;
do i=is,ie
260 res_fn = 0.5*(varmix%Res_fn_h(i,j) + varmix%Res_fn_h(i,j+1))
261 kh_v(i,j) = max(cs%KhTr * res_fn, cs%KhTr_min)
262 khdt_y(i,j) = dt*(cs%KhTr*(g%dx_Cv(i,j)*g%IdyCv(i,j))) * res_fn
265 if (cs%id_KhTr_u > 0)
then
267 do j=js,je ;
do i=is-1,ie
269 khdt_x(i,j) = dt*(cs%KhTr*(g%dy_Cu(i,j)*g%IdxCu(i,j)))
273 do j=js,je ;
do i=is-1,ie
274 khdt_x(i,j) = dt*(cs%KhTr*(g%dy_Cu(i,j)*g%IdxCu(i,j)))
277 if (cs%id_KhTr_v > 0)
then
279 do j=js-1,je ;
do i=is,ie
281 khdt_y(i,j) = dt*(cs%KhTr*(g%dx_Cv(i,j)*g%IdyCv(i,j)))
285 do j=js-1,je ;
do i=is,ie
286 khdt_y(i,j) = dt*(cs%KhTr*(g%dx_Cv(i,j)*g%IdyCv(i,j)))
291 if (cs%max_diff_CFL > 0.0)
then
292 if ((cs%id_KhTr_u > 0) .or. (cs%id_KhTr_h > 0))
then
294 do j=js,je ;
do i=is-1,ie
295 khdt_max = 0.125*cs%max_diff_CFL * min(g%areaT(i,j), g%areaT(i+1,j))
296 if (khdt_x(i,j) > khdt_max)
then
297 khdt_x(i,j) = khdt_max
298 if (dt*(g%dy_Cu(i,j)*g%IdxCu(i,j)) > 0.0) &
299 kh_u(i,j) = khdt_x(i,j) / (dt*(g%dy_Cu(i,j)*g%IdxCu(i,j)))
304 do j=js,je ;
do i=is-1,ie
305 khdt_max = 0.125*cs%max_diff_CFL * min(g%areaT(i,j), g%areaT(i+1,j))
306 khdt_x(i,j) = min(khdt_x(i,j), khdt_max)
309 if ((cs%id_KhTr_v > 0) .or. (cs%id_KhTr_h > 0))
then
311 do j=js-1,je ;
do i=is,ie
312 khdt_max = 0.125*cs%max_diff_CFL * min(g%areaT(i,j), g%areaT(i,j+1))
313 if (khdt_y(i,j) > khdt_max)
then
314 khdt_y(i,j) = khdt_max
315 if (dt*(g%dx_Cv(i,j)*g%IdyCv(i,j)) > 0.0) &
316 kh_v(i,j) = khdt_y(i,j) / (dt*(g%dx_Cv(i,j)*g%IdyCv(i,j)))
321 do j=js-1,je ;
do i=is,ie
322 khdt_max = 0.125*cs%max_diff_CFL * min(g%areaT(i,j), g%areaT(i,j+1))
323 khdt_y(i,j) = min(khdt_y(i,j), khdt_max)
330 do j=js,je ;
do i=is-1,ie
331 khdt_x(i,j) = read_khdt_x(i,j)
334 do j=js-1,je ;
do i=is,ie
335 khdt_y(i,j) = read_khdt_y(i,j)
340 if (cs%check_diffusive_CFL)
then
341 if (cs%show_call_tree)
call calltree_waypoint(
"Checking diffusive CFL (tracer_hordiff)")
343 do j=js,je ;
do i=is,ie
344 cfl(i,j) = 2.0*((khdt_x(i-1,j) + khdt_x(i,j)) + &
345 (khdt_y(i,j-1) + khdt_y(i,j))) * g%IareaT(i,j)
346 if (max_cfl < cfl(i,j)) max_cfl = cfl(i,j)
348 call cpu_clock_begin(id_clock_sync)
349 call max_across_pes(max_cfl)
350 call cpu_clock_end(id_clock_sync)
351 num_itts = max(1, ceiling(max_cfl - 4.0*epsilon(max_cfl)))
352 i_numitts = 1.0 / (real(num_itts))
353 if (cs%id_CFL > 0)
call post_data(cs%id_CFL, cfl, cs%diag, mask=g%mask2dT)
354 elseif (cs%max_diff_CFL > 0.0)
then
355 num_itts = max(1, ceiling(cs%max_diff_CFL - 4.0*epsilon(cs%max_diff_CFL)))
356 i_numitts = 1.0 / (real(num_itts))
358 num_itts = 1 ; i_numitts = 1.0
362 if (
associated(reg%Tr(m)%df_x))
then
363 do k=1,nz ;
do j=js,je ;
do i=is-1,ie
364 reg%Tr(m)%df_x(i,j,k) = 0.0
365 enddo ;
enddo ;
enddo
367 if (
associated(reg%Tr(m)%df_y))
then
368 do k=1,nz ;
do j=js-1,je ;
do i=is,ie
369 reg%Tr(m)%df_y(i,j,k) = 0.0
370 enddo ;
enddo ;
enddo
372 if (
associated(reg%Tr(m)%df2d_x))
then
373 do j=js,je ;
do i=is-1,ie ; reg%Tr(m)%df2d_x(i,j) = 0.0 ;
enddo ;
enddo
375 if (
associated(reg%Tr(m)%df2d_y))
then
376 do j=js-1,je ;
do i=is,ie ; reg%Tr(m)%df2d_y(i,j) = 0.0 ;
enddo ;
enddo
380 if (cs%use_neutral_diffusion)
then
382 if (cs%show_call_tree)
call calltree_waypoint(
"Calling neutral diffusion coeffs (tracer_hordiff)")
384 call do_group_pass(cs%pass_t, g%Domain, clock=id_clock_pass)
389 call neutral_diffusion_calc_coeffs(g, gv, h, tv%T, tv%S, cs%neutral_diffusion_CSp)
390 do j=js-1,je ;
do i=is,ie
391 coef_y(i,j) = i_numitts * khdt_y(i,j)
395 coef_x(i,j) = i_numitts * khdt_x(i,j)
400 if (cs%show_call_tree)
call calltree_waypoint(
"Calling neutral diffusion (tracer_hordiff)",itt)
402 call do_group_pass(cs%pass_t, g%Domain, clock=id_clock_pass)
404 call neutral_diffusion(g, gv, h, coef_x, coef_y, i_numitts*dt, reg, cs%neutral_diffusion_CSp)
409 if (cs%show_call_tree)
call calltree_waypoint(
"Calculating horizontal diffusion (tracer_hordiff)")
411 call do_group_pass(cs%pass_t, g%Domain, clock=id_clock_pass)
415 if (cs%Diffuse_ML_interior)
then
417 if (cs%ML_KhTr_scale <= 0.0) cycle
418 scale = i_numitts * cs%ML_KhTr_scale
420 if ((k>gv%nkml) .and. (k<=gv%nk_rho_varies)) cycle
423 do j=js-1,je ;
do i=is,ie
424 coef_y(i,j) = ((scale * khdt_y(i,j))*2.0*(h(i,j,k)*h(i,j+1,k))) / &
425 (h(i,j,k)+h(i,j+1,k)+h_neglect)
430 coef_x(i,j) = ((scale * khdt_x(i,j))*2.0*(h(i,j,k)*h(i+1,j,k))) / &
431 (h(i,j,k)+h(i+1,j,k)+h_neglect)
435 ihdxdy(i,j) = g%IareaT(i,j) / (h(i,j,k)+h_neglect)
440 do j=js,je ;
do i=is,ie
441 dtr(i,j) = ihdxdy(i,j) * &
442 ((coef_x(i-1,j) * (reg%Tr(m)%t(i-1,j,k) - reg%Tr(m)%t(i,j,k)) - &
443 coef_x(i,j) * (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i+1,j,k))) + &
444 (coef_y(i,j-1) * (reg%Tr(m)%t(i,j-1,k) - reg%Tr(m)%t(i,j,k)) - &
445 coef_y(i,j) * (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i,j+1,k))))
447 if (
associated(reg%Tr(m)%df_x))
then ;
do j=js,je ;
do i=g%IscB,g%IecB
448 reg%Tr(m)%df_x(i,j,k) = reg%Tr(m)%df_x(i,j,k) + coef_x(i,j) * &
449 (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i+1,j,k))*idt
450 enddo ;
enddo ;
endif
451 if (
associated(reg%Tr(m)%df_y))
then ;
do j=g%JscB,g%JecB ;
do i=is,ie
452 reg%Tr(m)%df_y(i,j,k) = reg%Tr(m)%df_y(i,j,k) + coef_y(i,j) * &
453 (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i,j+1,k))*idt
454 enddo ;
enddo ;
endif
455 if (
associated(reg%Tr(m)%df2d_x))
then ;
do j=js,je ;
do i=g%IscB,g%IecB
456 reg%Tr(m)%df2d_x(i,j) = reg%Tr(m)%df2d_x(i,j) + coef_x(i,j) * &
457 (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i+1,j,k))*idt
458 enddo ;
enddo ;
endif
459 if (
associated(reg%Tr(m)%df2d_y))
then ;
do j=g%JscB,g%JecB ;
do i=is,ie
460 reg%Tr(m)%df2d_y(i,j) = reg%Tr(m)%df2d_y(i,j) + coef_y(i,j) * &
461 (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i,j+1,k))*idt
462 enddo ;
enddo ;
endif
463 do j=js,je ;
do i=is,ie
464 reg%Tr(m)%t(i,j,k) = reg%Tr(m)%t(i,j,k) + dtr(i,j)
473 call cpu_clock_end(id_clock_diffuse)
476 if (cs%Diffuse_ML_interior)
then
477 if (cs%show_call_tree)
call calltree_waypoint(
"Calling epipycnal_ML_diff (tracer_hordiff)")
478 if (cs%debug)
call mom_tracer_chksum(
"Before epipycnal diff ", reg%Tr, ntr, g)
480 call cpu_clock_begin(id_clock_epimix)
481 call tracer_epipycnal_ml_diff(h, dt, reg%Tr, ntr, khdt_x, khdt_y, g, gv, &
483 call cpu_clock_end(id_clock_epimix)
486 if (cs%debug)
call mom_tracer_chksum(
"After tracer diffusion ", reg%Tr, ntr, g)
489 if (cs%id_KhTr_u > 0)
then
490 do j=js,je ;
do i=is-1,ie
491 kh_u(i,j) = g%mask2dCu(i,j)*kh_u(i,j)
493 call post_data(cs%id_KhTr_u, kh_u, cs%diag, mask=g%mask2dCu)
495 if (cs%id_KhTr_v > 0)
then
496 do j=js-1,je ;
do i=is,ie
497 kh_v(i,j) = g%mask2dCv(i,j)*kh_v(i,j)
499 call post_data(cs%id_KhTr_v, kh_v, cs%diag, mask=g%mask2dCv)
501 if (cs%id_KhTr_h > 0)
then
503 do j=js,je ;
do i=is-1,ie
504 kh_u(i,j) = g%mask2dCu(i,j)*kh_u(i,j)
506 do j=js-1,je ;
do i=is,ie
507 kh_v(i,j) = g%mask2dCv(i,j)*kh_v(i,j)
509 do j=js,je ;
do i=is,ie
510 normalize = 1.0 / ((g%mask2dCu(i-1,j)+g%mask2dCu(i,j)) + &
511 (g%mask2dCv(i,j-1)+g%mask2dCv(i,j)) + gv%H_subroundoff)
512 kh_h(i,j) = normalize*g%mask2dT(i,j)*((kh_u(i-1,j)+kh_u(i,j)) + &
513 (kh_v(i,j-1)+kh_v(i,j)))
515 call post_data(cs%id_KhTr_h, kh_h, cs%diag, mask=g%mask2dT)
520 call uvchksum(
"After tracer diffusion khdt_[xy]", khdt_x, khdt_y, &
521 g%HI, haloshift=0, symmetric=.true.)
522 if (cs%use_neutral_diffusion)
then
523 call uvchksum(
"After tracer diffusion Coef_[xy]", coef_x, coef_y, &
524 g%HI, haloshift=0, symmetric=.true.)
528 if (cs%id_khdt_x > 0)
call post_data(cs%id_khdt_x, khdt_x, cs%diag)
529 if (cs%id_khdt_y > 0)
call post_data(cs%id_khdt_y, khdt_y, cs%diag)
531 if (cs%show_call_tree)
call calltree_leave(
"tracer_hordiff()")
533 end subroutine tracer_hordiff
539 subroutine tracer_epipycnal_ml_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
540 GV, CS, tv, num_itts)
543 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
544 real,
intent(in) :: dt
546 integer,
intent(in) :: ntr
547 real,
dimension(SZIB_(G),SZJ_(G)),
intent(in) :: khdt_epi_x
548 real,
dimension(SZI_(G),SZJB_(G)),
intent(in) :: khdt_epi_y
551 integer,
intent(in) :: num_itts
554 real,
dimension(SZI_(G), SZJ_(G)) :: &
556 real,
dimension(SZI_(G), SZJ_(G), max(1,GV%nk_rho_varies)) :: &
561 type(
p2d),
dimension(SZJ_(G)) :: &
562 deep_wt_Lu, deep_wt_Ru, &
565 type(
p2d),
dimension(SZJB_(G)) :: &
566 deep_wt_Lv, deep_wt_Rv, &
569 type(
p2di),
dimension(SZJ_(G)) :: &
572 type(
p2di),
dimension(SZJB_(G)) :: &
576 real,
dimension(SZI_(G), SZJ_(G), SZK_(G)) :: &
578 real,
dimension(SZI_(G), SZJ_(G), SZK_(G)) :: Tr_flux_3d, Tr_adj_vert_L, Tr_adj_vert_R
580 real,
dimension(SZI_(G), SZK_(G), SZJ_(G)) :: &
583 integer,
dimension(SZI_(G), SZK_(G), SZJ_(G)) :: &
587 real,
dimension(SZK_(G)) :: &
594 integer,
dimension(SZK_(G)) :: &
598 integer,
dimension(SZI_(G), SZJ_(G)) :: &
604 integer,
dimension(SZJ_(G)) :: &
606 integer,
dimension(SZIB_(G), SZJ_(G)) :: &
608 integer,
dimension(SZI_(G), SZJB_(G)) :: &
614 real :: rho_pair, rho_a, rho_b
627 logical,
dimension(SZK_(G)) :: &
631 real :: p_ref_cv(SZI_(G))
633 integer :: k_max, k_min, k_test, itmp
634 integer :: i, j, k, k2, m, is, ie, js, je, nz, nkmb
635 integer :: isd, ied, jsd, jed, IsdB, IedB, k_size
636 integer :: kL, kR, kLa, kLb, kRa, kRb, nP, itt, ns, max_itt
637 integer :: PEmax_kRho
638 integer :: isv, iev, jsv, jev
640 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
641 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
642 isdb = g%IsdB ; iedb = g%IedB
644 nkmb = gv%nk_rho_varies
646 if (num_itts <= 1)
then
647 max_itt = 1 ; i_maxitt = 1.0
649 max_itt = num_itts ; i_maxitt = 1.0 / (real(max_itt))
652 do i=is-2,ie+2 ; p_ref_cv(i) = tv%P_Ref ;
enddo
654 call do_group_pass(cs%pass_t, g%Domain, clock=id_clock_pass)
657 do k=1,nkmb ;
do j=js-2,je+2
659 rho_coord(:,j,k), is-2, ie-is+5, tv%eqn_of_state)
662 do j=js-2,je+2 ;
do i=is-2,ie+2
663 rml_max(i,j) = rho_coord(i,j,1)
664 num_srt(i,j) = 0 ; max_krho(i,j) = 0
666 do k=2,nkmb ;
do j=js-2,je+2 ;
do i=is-2,ie+2
667 if (rml_max(i,j) < rho_coord(i,j,k)) rml_max(i,j) = rho_coord(i,j,k)
668 enddo ;
enddo ;
enddo
674 do j=js-2,je+2 ;
do i=is-2,ie+2 ;
if (g%mask2dT(i,j) > 0.5)
then
675 if (rml_max(i,j) > gv%Rlay(nz))
then ; max_krho(i,j) = nz+1
676 elseif (rml_max(i,j) <= gv%Rlay(nkmb+1))
then ; max_krho(i,j) = nkmb+1
678 k_min = nkmb+2 ; k_max = nz
680 k_test = (k_min + k_max) / 2
681 if (rml_max(i,j) <= gv%Rlay(k_test-1))
then ; k_max = k_test-1
682 elseif (gv%Rlay(k_test) < rml_max(i,j))
then ; k_min = k_test+1
683 else ; max_krho(i,j) = k_test ;
exit ;
endif
685 if (k_min == k_max)
then ; max_krho(i,j) = k_max ;
exit ;
endif
688 endif ;
enddo ;
enddo
691 do j=js-1,je+1 ;
do i=is-1,ie+1
692 k_end_srt(i,j) = max(max_krho(i,j), max_krho(i-1,j), max_krho(i+1,j), &
693 max_krho(i,j-1), max_krho(i,j+1))
694 if (pemax_krho < k_end_srt(i,j)) pemax_krho = k_end_srt(i,j)
696 if (pemax_krho > nz) pemax_krho = nz
698 h_exclude = 10.0*(gv%Angstrom_H + gv%H_subroundoff)
704 do k=1,nkmb ;
do i=is-1,ie+1 ;
if (g%mask2dT(i,j) > 0.5)
then
705 if (h(i,j,k) > h_exclude)
then
706 num_srt(i,j) = num_srt(i,j) + 1 ; ns = num_srt(i,j)
708 rho_srt(i,ns,j) = rho_coord(i,j,k)
709 h_srt(i,ns,j) = h(i,j,k)
711 endif ;
enddo ;
enddo
712 do k=nkmb+1,pemax_krho ;
do i=is-1,ie+1 ;
if (g%mask2dT(i,j) > 0.5)
then
713 if ((k<=k_end_srt(i,j)) .and. (h(i,j,k) > h_exclude))
then
714 num_srt(i,j) = num_srt(i,j) + 1 ; ns = num_srt(i,j)
716 rho_srt(i,ns,j) = gv%Rlay(k)
717 h_srt(i,ns,j) = h(i,j,k)
719 endif ;
enddo ;
enddo
724 do j=js-1,je+1;
do i=is-1,ie+1
725 do k=2,num_srt(i,j) ;
if (rho_srt(i,k,j) < rho_srt(i,k-1,j))
then
727 do k2 = k,2,-1 ;
if (rho_srt(i,k2,j) >= rho_srt(i,k2-1,j))
exit
728 itmp = k0_srt(i,k2-1,j) ; k0_srt(i,k2-1,j) = k0_srt(i,k2,j) ; k0_srt(i,k2,j) = itmp
729 tmp = rho_srt(i,k2-1,j) ; rho_srt(i,k2-1,j) = rho_srt(i,k2,j) ; rho_srt(i,k2,j) = tmp
730 tmp = h_srt(i,k2-1,j) ; h_srt(i,k2-1,j) = h_srt(i,k2,j) ; h_srt(i,k2,j) = tmp
737 do i=is-1,ie+1 ; max_srt(j) = max(max_srt(j), num_srt(i,j)) ;
enddo
742 k_size = max(2*max_srt(j),1)
743 allocate(deep_wt_lu(j)%p(isdb:iedb,k_size))
744 allocate(deep_wt_ru(j)%p(isdb:iedb,k_size))
745 allocate(hp_lu(j)%p(isdb:iedb,k_size))
746 allocate(hp_ru(j)%p(isdb:iedb,k_size))
747 allocate(k0a_lu(j)%p(isdb:iedb,k_size))
748 allocate(k0a_ru(j)%p(isdb:iedb,k_size))
749 allocate(k0b_lu(j)%p(isdb:iedb,k_size))
750 allocate(k0b_ru(j)%p(isdb:iedb,k_size))
760 do j=js,je ;
do i=is-1,ie ;
if (g%mask2dCu(i,j) > 0.5)
then
763 do k=1,num_srt(i,j) ; h_demand_l(k) = 0.0 ; h_used_l(k) = 0.0 ;
enddo
764 do k=1,num_srt(i+1,j) ; h_demand_r(k) = 0.0 ; h_used_r(k) = 0.0 ;
enddo
771 if (rho_srt(i,1,j) < rho_srt(i+1,1,j))
then
773 do kl=2,num_srt(i,j) ;
if (rho_srt(i,kl,j) >= rho_srt(i+1,1,j))
exit ;
enddo
774 elseif (rho_srt(i+1,1,j) < rho_srt(i,1,j))
then
776 do kr=2,num_srt(i+1,j) ;
if (rho_srt(i+1,kr,j) >= rho_srt(i,1,j))
exit ;
enddo
782 if ((kl > num_srt(i,j)) .or. (kr > num_srt(i+1,j)))
exit
784 if (rho_srt(i,kl,j) > rho_srt(i+1,kr,j))
then
787 rho_pair = rho_srt(i+1,kr,j)
789 k0b_lu(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_ru(j)%p(i,k) = k0_srt(i+1,kr,j)
790 k0a_lu(j)%p(i,k) = k0_srt(i,kl-1,j) ; k0a_ru(j)%p(i,k) = k0b_ru(j)%p(i,k)
791 kbs_lp(k) = kl ; kbs_rp(k) = kr
793 rho_a = rho_srt(i,kl-1,j) ; rho_b = rho_srt(i,kl,j)
794 wt_b = 1.0 ;
if (abs(rho_a - rho_b) > abs(rho_pair - rho_a)) &
795 wt_b = (rho_pair - rho_a) / (rho_b - rho_a)
796 deep_wt_lu(j)%p(i,k) = wt_b ; deep_wt_ru(j)%p(i,k) = 1.0
798 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i+1,kr,j) * wt_b
799 h_demand_l(kl-1) = h_demand_l(kl-1) + 0.5*h_srt(i+1,kr,j) * (1.0-wt_b)
801 kr = kr+1 ; left_set(k) = .false. ; right_set(k) = .true.
802 elseif (rho_srt(i,kl,j) < rho_srt(i+1,kr,j))
then
805 rho_pair = rho_srt(i,kl,j)
806 k0b_lu(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_ru(j)%p(i,k) = k0_srt(i+1,kr,j)
807 k0a_lu(j)%p(i,k) = k0b_lu(j)%p(i,k) ; k0a_ru(j)%p(i,k) = k0_srt(i+1,kr-1,j)
809 kbs_lp(k) = kl ; kbs_rp(k) = kr
811 rho_a = rho_srt(i+1,kr-1,j) ; rho_b = rho_srt(i+1,kr,j)
812 wt_b = 1.0 ;
if (abs(rho_a - rho_b) > abs(rho_pair - rho_a)) &
813 wt_b = (rho_pair - rho_a) / (rho_b - rho_a)
814 deep_wt_lu(j)%p(i,k) = 1.0 ; deep_wt_ru(j)%p(i,k) = wt_b
816 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j) * wt_b
817 h_demand_r(kr-1) = h_demand_r(kr-1) + 0.5*h_srt(i,kl,j) * (1.0-wt_b)
819 kl = kl+1 ; left_set(k) = .true. ; right_set(k) = .false.
820 elseif ((k0_srt(i,kl,j) <= nkmb) .or. (k0_srt(i+1,kr,j) <= nkmb))
then
823 k0b_lu(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_ru(j)%p(i,k) = k0_srt(i+1,kr,j)
824 k0a_lu(j)%p(i,k) = k0b_lu(j)%p(i,k) ; k0a_ru(j)%p(i,k) = k0b_ru(j)%p(i,k)
825 kbs_lp(k) = kl ; kbs_rp(k) = kr
826 deep_wt_lu(j)%p(i,k) = 1.0 ; deep_wt_ru(j)%p(i,k) = 1.0
828 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i+1,kr,j)
829 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j)
831 kl = kl+1 ; kr = kr+1 ; left_set(k) = .true. ; right_set(k) = .true.
835 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i+1,kr,j)
836 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j)
838 kl = kl+1 ; kr = kr+1
844 do k=1,num_srt(i+1,j)
845 h_supply_frac_r(k) = 1.0
846 if (h_demand_r(k) > 0.5*h_srt(i+1,k,j)) &
847 h_supply_frac_r(k) = 0.5*h_srt(i+1,k,j) / h_demand_r(k)
850 h_supply_frac_l(k) = 1.0
851 if (h_demand_l(k) > 0.5*h_srt(i,k,j)) &
852 h_supply_frac_l(k) = 0.5*h_srt(i,k,j) / h_demand_l(k)
857 kl = kbs_lp(k) ; kr = kbs_rp(k)
858 hp_lu(j)%p(i,k) = 0.0 ; hp_ru(j)%p(i,k) = 0.0
859 if (left_set(k))
then
860 if (deep_wt_ru(j)%p(i,k) < 1.0)
then
861 hp_ru(j)%p(i,k) = 0.5*h_srt(i,kl,j) * min(h_supply_frac_r(kr), h_supply_frac_r(kr-1))
862 wt_b = deep_wt_ru(j)%p(i,k)
863 h_used_r(kr-1) = h_used_r(kr-1) + (1.0 - wt_b)*hp_ru(j)%p(i,k)
864 h_used_r(kr) = h_used_r(kr) + wt_b*hp_ru(j)%p(i,k)
866 hp_ru(j)%p(i,k) = 0.5*h_srt(i,kl,j) * h_supply_frac_r(kr)
867 h_used_r(kr) = h_used_r(kr) + hp_ru(j)%p(i,k)
870 if (right_set(k))
then
871 if (deep_wt_lu(j)%p(i,k) < 1.0)
then
872 hp_lu(j)%p(i,k) = 0.5*h_srt(i+1,kr,j) * min(h_supply_frac_l(kl), h_supply_frac_l(kl-1))
873 wt_b = deep_wt_lu(j)%p(i,k)
874 h_used_l(kl-1) = h_used_l(kl-1) + (1.0 - wt_b)*hp_lu(j)%p(i,k)
875 h_used_l(kl) = h_used_l(kl) + wt_b*hp_lu(j)%p(i,k)
877 hp_lu(j)%p(i,k) = 0.5*h_srt(i+1,kr,j) * h_supply_frac_l(kl)
878 h_used_l(kl) = h_used_l(kl) + hp_lu(j)%p(i,k)
886 if (left_set(k)) hp_lu(j)%p(i,k) = hp_lu(j)%p(i,k) + &
887 (h_srt(i,kbs_lp(k),j) - h_used_l(kbs_lp(k)))
888 if (right_set(k)) hp_ru(j)%p(i,k) = hp_ru(j)%p(i,k) + &
889 (h_srt(i+1,kbs_rp(k),j) - h_used_r(kbs_rp(k)))
892 endif ;
enddo ;
enddo
895 k_size = max(max_srt(j)+max_srt(j+1),1)
896 allocate(deep_wt_lv(j)%p(isd:ied,k_size))
897 allocate(deep_wt_rv(j)%p(isd:ied,k_size))
898 allocate(hp_lv(j)%p(isd:ied,k_size))
899 allocate(hp_rv(j)%p(isd:ied,k_size))
900 allocate(k0a_lv(j)%p(isd:ied,k_size))
901 allocate(k0a_rv(j)%p(isd:ied,k_size))
902 allocate(k0b_lv(j)%p(isd:ied,k_size))
903 allocate(k0b_rv(j)%p(isd:ied,k_size))
913 do j=js-1,je ;
do i=is,ie ;
if (g%mask2dCv(i,j) > 0.5)
then
916 do k=1,num_srt(i,j) ; h_demand_l(k) = 0.0 ; h_used_l(k) = 0.0 ;
enddo
917 do k=1,num_srt(i,j+1) ; h_demand_r(k) = 0.0 ; h_used_r(k) = 0.0 ;
enddo
924 if (rho_srt(i,1,j) < rho_srt(i,1,j+1))
then
926 do kl=2,num_srt(i,j) ;
if (rho_srt(i,kl,j) >= rho_srt(i,1,j+1))
exit ;
enddo
927 elseif (rho_srt(i,1,j+1) < rho_srt(i,1,j))
then
929 do kr=2,num_srt(i,j+1) ;
if (rho_srt(i,kr,j+1) >= rho_srt(i,1,j))
exit ;
enddo
935 if ((kl > num_srt(i,j)) .or. (kr > num_srt(i,j+1)))
exit
937 if (rho_srt(i,kl,j) > rho_srt(i,kr,j+1))
then
940 rho_pair = rho_srt(i,kr,j+1)
942 k0b_lv(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_rv(j)%p(i,k) = k0_srt(i,kr,j+1)
943 k0a_lv(j)%p(i,k) = k0_srt(i,kl-1,j) ; k0a_rv(j)%p(i,k) = k0b_rv(j)%p(i,k)
944 kbs_lp(k) = kl ; kbs_rp(k) = kr
946 rho_a = rho_srt(i,kl-1,j) ; rho_b = rho_srt(i,kl,j)
947 wt_b = 1.0 ;
if (abs(rho_a - rho_b) > abs(rho_pair - rho_a)) &
948 wt_b = (rho_pair - rho_a) / (rho_b - rho_a)
949 deep_wt_lv(j)%p(i,k) = wt_b ; deep_wt_rv(j)%p(i,k) = 1.0
951 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i,kr,j+1) * wt_b
952 h_demand_l(kl-1) = h_demand_l(kl-1) + 0.5*h_srt(i,kr,j+1) * (1.0-wt_b)
954 kr = kr+1 ; left_set(k) = .false. ; right_set(k) = .true.
955 elseif (rho_srt(i,kl,j) < rho_srt(i,kr,j+1))
then
958 rho_pair = rho_srt(i,kl,j)
959 k0b_lv(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_rv(j)%p(i,k) = k0_srt(i,kr,j+1)
960 k0a_lv(j)%p(i,k) = k0b_lv(j)%p(i,k) ; k0a_rv(j)%p(i,k) = k0_srt(i,kr-1,j+1)
962 kbs_lp(k) = kl ; kbs_rp(k) = kr
964 rho_a = rho_srt(i,kr-1,j+1) ; rho_b = rho_srt(i,kr,j+1)
965 wt_b = 1.0 ;
if (abs(rho_a - rho_b) > abs(rho_pair - rho_a)) &
966 wt_b = (rho_pair - rho_a) / (rho_b - rho_a)
967 deep_wt_lv(j)%p(i,k) = 1.0 ; deep_wt_rv(j)%p(i,k) = wt_b
969 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j) * wt_b
970 h_demand_r(kr-1) = h_demand_r(kr-1) + 0.5*h_srt(i,kl,j) * (1.0-wt_b)
972 kl = kl+1 ; left_set(k) = .true. ; right_set(k) = .false.
973 elseif ((k0_srt(i,kl,j) <= nkmb) .or. (k0_srt(i,kr,j+1) <= nkmb))
then
976 k0b_lv(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_rv(j)%p(i,k) = k0_srt(i,kr,j+1)
977 k0a_lv(j)%p(i,k) = k0b_lv(j)%p(i,k) ; k0a_rv(j)%p(i,k) = k0b_rv(j)%p(i,k)
978 kbs_lp(k) = kl ; kbs_rp(k) = kr
979 deep_wt_lv(j)%p(i,k) = 1.0 ; deep_wt_rv(j)%p(i,k) = 1.0
981 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i,kr,j+1)
982 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j)
984 kl = kl+1 ; kr = kr+1 ; left_set(k) = .true. ; right_set(k) = .true.
988 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i,kr,j+1)
989 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j)
991 kl = kl+1 ; kr = kr+1
997 do k=1,num_srt(i,j+1)
998 h_supply_frac_r(k) = 1.0
999 if (h_demand_r(k) > 0.5*h_srt(i,k,j+1)) &
1000 h_supply_frac_r(k) = 0.5*h_srt(i,k,j+1) / h_demand_r(k)
1003 h_supply_frac_l(k) = 1.0
1004 if (h_demand_l(k) > 0.5*h_srt(i,k,j)) &
1005 h_supply_frac_l(k) = 0.5*h_srt(i,k,j) / h_demand_l(k)
1010 kl = kbs_lp(k) ; kr = kbs_rp(k)
1011 hp_lv(j)%p(i,k) = 0.0 ; hp_rv(j)%p(i,k) = 0.0
1012 if (left_set(k))
then
1013 if (deep_wt_rv(j)%p(i,k) < 1.0)
then
1014 hp_rv(j)%p(i,k) = 0.5*h_srt(i,kl,j) * min(h_supply_frac_r(kr), h_supply_frac_r(kr-1))
1015 wt_b = deep_wt_rv(j)%p(i,k)
1016 h_used_r(kr-1) = h_used_r(kr-1) + (1.0 - wt_b) * hp_rv(j)%p(i,k)
1017 h_used_r(kr) = h_used_r(kr) + wt_b * hp_rv(j)%p(i,k)
1019 hp_rv(j)%p(i,k) = 0.5*h_srt(i,kl,j) * h_supply_frac_r(kr)
1020 h_used_r(kr) = h_used_r(kr) + hp_rv(j)%p(i,k)
1023 if (right_set(k))
then
1024 if (deep_wt_lv(j)%p(i,k) < 1.0)
then
1025 hp_lv(j)%p(i,k) = 0.5*h_srt(i,kr,j+1) * min(h_supply_frac_l(kl), h_supply_frac_l(kl-1))
1026 wt_b = deep_wt_lv(j)%p(i,k)
1027 h_used_l(kl-1) = h_used_l(kl-1) + (1.0 - wt_b) * hp_lv(j)%p(i,k)
1028 h_used_l(kl) = h_used_l(kl) + wt_b * hp_lv(j)%p(i,k)
1030 hp_lv(j)%p(i,k) = 0.5*h_srt(i,kr,j+1) * h_supply_frac_l(kl)
1031 h_used_l(kl) = h_used_l(kl) + hp_lv(j)%p(i,k)
1039 if (left_set(k)) hp_lv(j)%p(i,k) = hp_lv(j)%p(i,k) + &
1040 (h_srt(i,kbs_lp(k),j) - h_used_l(kbs_lp(k)))
1041 if (right_set(k)) hp_rv(j)%p(i,k) = hp_rv(j)%p(i,k) + &
1042 (h_srt(i,kbs_rp(k),j+1) - h_used_r(kbs_rp(k)))
1046 endif ;
enddo ;
enddo
1051 do k=1,pemax_krho ;
do j=js-1,je+1 ;
do i=is-1,ie+1
1052 tr_flux_conv(i,j,k) = 0.0
1053 enddo ;
enddo ;
enddo
1058 call do_group_pass(cs%pass_t, g%Domain, clock=id_clock_pass)
1068 do j=js,je ;
do i=is-1,ie ;
if (g%mask2dCu(i,j) > 0.5)
then
1072 if (npu(i,j) >= 1)
then
1073 tr_min_face = min(tr(m)%t(i,j,1), tr(m)%t(i+1,j,1))
1074 tr_max_face = max(tr(m)%t(i,j,1), tr(m)%t(i+1,j,1))
1076 tr_min_face = min(tr_min_face, tr(m)%t(i,j,k), tr(m)%t(i+1,j,k))
1077 tr_max_face = max(tr_max_face, tr(m)%t(i,j,k), tr(m)%t(i+1,j,k))
1081 kla = nkmb+1 ;
if (max_krho(i,j) < nz+1) kla = max_krho(i,j)
1082 klb = kla ;
if (max_krho(i,j) < nz) klb = max_krho(i,j)+1
1083 kra = nkmb+1 ;
if (max_krho(i+1,j) < nz+1) kra = max_krho(i+1,j)
1084 krb = kra ;
if (max_krho(i+1,j) < nz) krb = max_krho(i+1,j)+1
1085 tr_la = tr_min_face ; tr_lb = tr_la ; tr_ra = tr_la ; tr_rb = tr_la
1086 if (h(i,j,kla) > h_exclude) tr_la = tr(m)%t(i,j,kla)
1087 if (h(i,j,klb) > h_exclude) tr_la = tr(m)%t(i,j,klb)
1088 if (h(i+1,j,kra) > h_exclude) tr_ra = tr(m)%t(i+1,j,kra)
1089 if (h(i+1,j,krb) > h_exclude) tr_rb = tr(m)%t(i+1,j,krb)
1090 tr_min_face = min(tr_min_face, tr_la, tr_lb, tr_ra, tr_rb)
1091 tr_max_face = max(tr_max_face, tr_la, tr_lb, tr_ra, tr_rb)
1095 tr_lb = tr(m)%t(i,j,k0b_lu(j)%p(i,k))
1096 tr_rb = tr(m)%t(i+1,j,k0b_ru(j)%p(i,k))
1097 tr_la = tr_lb ; tr_ra = tr_rb
1098 if (deep_wt_lu(j)%p(i,k) < 1.0) tr_la = tr(m)%t(i,j,k0a_lu(j)%p(i,k))
1099 if (deep_wt_ru(j)%p(i,k) < 1.0) tr_ra = tr(m)%t(i+1,j,k0a_ru(j)%p(i,k))
1100 tr_min_face = min(tr_min_face, tr_la, tr_lb, tr_ra, tr_rb)
1101 tr_max_face = max(tr_max_face, tr_la, tr_lb, tr_ra, tr_rb)
1106 klb = k0b_lu(j)%p(i,k) ; tr_lb = tr(m)%t(i,j,klb) ; tr_av_l = tr_lb
1107 if (deep_wt_lu(j)%p(i,k) < 1.0)
then
1108 kla = k0a_lu(j)%p(i,k) ; tr_la = tr(m)%t(i,j,kla)
1109 wt_b = deep_wt_lu(j)%p(i,k)
1110 tr_av_l = wt_b*tr_lb + (1.0-wt_b)*tr_la
1113 krb = k0b_ru(j)%p(i,k) ; tr_rb = tr(m)%t(i+1,j,krb) ; tr_av_r = tr_rb
1114 if (deep_wt_ru(j)%p(i,k) < 1.0)
then
1115 kra = k0a_ru(j)%p(i,k) ; tr_ra = tr(m)%t(i+1,j,kra)
1116 wt_b = deep_wt_ru(j)%p(i,k)
1117 tr_av_r = wt_b*tr_rb + (1.0-wt_b)*tr_ra
1120 h_l = hp_lu(j)%p(i,k) ; h_r = hp_ru(j)%p(i,k)
1121 tr_flux = i_maxitt * khdt_epi_x(i,j) * (tr_av_l - tr_av_r) * &
1122 ((2.0 * h_l * h_r) / (h_l + h_r))
1125 if (deep_wt_lu(j)%p(i,k) >= 1.0)
then
1126 tr_flux_conv(i,j,klb) = tr_flux_conv(i,j,klb) - tr_flux
1129 wt_b = deep_wt_lu(j)%p(i,k) ; wt_a = 1.0 - wt_b
1130 vol = hp_lu(j)%p(i,k) * g%areaT(i,j)
1138 if (tr_flux > 0.0)
then
1139 if (tr_la < tr_lb)
then ;
if (vol*(tr_la-tr_min_face) < tr_flux) &
1140 tr_adj_vert = -wt_a * min(tr_flux - vol * (tr_la-tr_min_face), &
1141 (vol*wt_b) * (tr_lb - tr_la))
1142 else ;
if (vol*(tr_lb-tr_min_face) < tr_flux) &
1143 tr_adj_vert = wt_b * min(tr_flux - vol * (tr_lb-tr_min_face), &
1144 (vol*wt_a) * (tr_la - tr_lb))
1146 elseif (tr_flux < 0.0)
then
1147 if (tr_la > tr_lb)
then ;
if (vol * (tr_max_face-tr_la) < -tr_flux) &
1148 tr_adj_vert = wt_a * min(-tr_flux - vol * (tr_max_face-tr_la), &
1149 (vol*wt_b) * (tr_la - tr_lb))
1150 else ;
if (vol*(tr_max_face-tr_lb) < -tr_flux) &
1151 tr_adj_vert = -wt_b * min(-tr_flux - vol * (tr_max_face-tr_lb), &
1152 (vol*wt_a)*(tr_lb - tr_la))
1156 tr_flux_conv(i,j,kla) = tr_flux_conv(i,j,kla) - (wt_a*tr_flux + tr_adj_vert)
1157 tr_flux_conv(i,j,klb) = tr_flux_conv(i,j,klb) - (wt_b*tr_flux - tr_adj_vert)
1160 if (deep_wt_ru(j)%p(i,k) >= 1.0)
then
1161 tr_flux_conv(i+1,j,krb) = tr_flux_conv(i+1,j,krb) + tr_flux
1164 wt_b = deep_wt_ru(j)%p(i,k) ; wt_a = 1.0 - wt_b
1165 vol = hp_ru(j)%p(i,k) * g%areaT(i+1,j)
1173 if (tr_flux < 0.0)
then
1174 if (tr_ra < tr_rb)
then ;
if (vol * (tr_ra-tr_min_face) < -tr_flux) &
1175 tr_adj_vert = -wt_a * min(-tr_flux - vol * (tr_ra-tr_min_face), &
1176 (vol*wt_b) * (tr_rb - tr_ra))
1177 else ;
if (vol*(tr_rb-tr_min_face) < (-tr_flux)) &
1178 tr_adj_vert = wt_b * min(-tr_flux - vol * (tr_rb-tr_min_face), &
1179 (vol*wt_a) * (tr_ra - tr_rb))
1181 elseif (tr_flux > 0.0)
then
1182 if (tr_ra > tr_rb)
then ;
if (vol * (tr_max_face-tr_ra) < tr_flux) &
1183 tr_adj_vert = wt_a * min(tr_flux - vol * (tr_max_face-tr_ra), &
1184 (vol*wt_b) * (tr_ra - tr_rb))
1185 else ;
if (vol*(tr_max_face-tr_rb) < tr_flux) &
1186 tr_adj_vert = -wt_b * min(tr_flux - vol * (tr_max_face-tr_rb), &
1187 (vol*wt_a)*(tr_rb - tr_ra))
1191 tr_flux_conv(i+1,j,kra) = tr_flux_conv(i+1,j,kra) + &
1192 (wt_a*tr_flux - tr_adj_vert)
1193 tr_flux_conv(i+1,j,krb) = tr_flux_conv(i+1,j,krb) + &
1194 (wt_b*tr_flux + tr_adj_vert)
1196 if (
associated(tr(m)%df2d_x)) &
1197 tr(m)%df2d_x(i,j) = tr(m)%df2d_x(i,j) + tr_flux * idt
1199 endif ;
enddo ;
enddo
1208 do j=js-1,je ;
do i=is,ie ;
if (g%mask2dCv(i,j) > 0.5)
then
1212 if (npv(i,j) >= 1)
then
1213 tr_min_face = min(tr(m)%t(i,j,1), tr(m)%t(i,j+1,1))
1214 tr_max_face = max(tr(m)%t(i,j,1), tr(m)%t(i,j+1,1))
1216 tr_min_face = min(tr_min_face, tr(m)%t(i,j,k), tr(m)%t(i,j+1,k))
1217 tr_max_face = max(tr_max_face, tr(m)%t(i,j,k), tr(m)%t(i,j+1,k))
1221 kla = nkmb+1 ;
if (max_krho(i,j) < nz+1) kla = max_krho(i,j)
1222 klb = kla ;
if (max_krho(i,j) < nz) klb = max_krho(i,j)+1
1223 kra = nkmb+1 ;
if (max_krho(i,j+1) < nz+1) kra = max_krho(i,j+1)
1224 krb = kra ;
if (max_krho(i,j+1) < nz) krb = max_krho(i,j+1)+1
1225 tr_la = tr_min_face ; tr_lb = tr_la ; tr_ra = tr_la ; tr_rb = tr_la
1226 if (h(i,j,kla) > h_exclude) tr_la = tr(m)%t(i,j,kla)
1227 if (h(i,j,klb) > h_exclude) tr_la = tr(m)%t(i,j,klb)
1228 if (h(i,j+1,kra) > h_exclude) tr_ra = tr(m)%t(i,j+1,kra)
1229 if (h(i,j+1,krb) > h_exclude) tr_rb = tr(m)%t(i,j+1,krb)
1230 tr_min_face = min(tr_min_face, tr_la, tr_lb, tr_ra, tr_rb)
1231 tr_max_face = max(tr_max_face, tr_la, tr_lb, tr_ra, tr_rb)
1235 tr_lb = tr(m)%t(i,j,k0b_lv(j)%p(i,k)) ; tr_rb = tr(m)%t(i,j+1,k0b_rv(j)%p(i,k))
1236 tr_la = tr_lb ; tr_ra = tr_rb
1237 if (deep_wt_lv(j)%p(i,k) < 1.0) tr_la = tr(m)%t(i,j,k0a_lv(j)%p(i,k))
1238 if (deep_wt_rv(j)%p(i,k) < 1.0) tr_ra = tr(m)%t(i,j+1,k0a_rv(j)%p(i,k))
1239 tr_min_face = min(tr_min_face, tr_la, tr_lb, tr_ra, tr_rb)
1240 tr_max_face = max(tr_max_face, tr_la, tr_lb, tr_ra, tr_rb)
1245 klb = k0b_lv(j)%p(i,k) ; tr_lb = tr(m)%t(i,j,klb) ; tr_av_l = tr_lb
1246 if (deep_wt_lv(j)%p(i,k) < 1.0)
then
1247 kla = k0a_lv(j)%p(i,k) ; tr_la = tr(m)%t(i,j,kla)
1248 wt_b = deep_wt_lv(j)%p(i,k)
1249 tr_av_l = wt_b * tr_lb + (1.0-wt_b) * tr_la
1252 krb = k0b_rv(j)%p(i,k) ; tr_rb = tr(m)%t(i,j+1,krb) ; tr_av_r = tr_rb
1253 if (deep_wt_rv(j)%p(i,k) < 1.0)
then
1254 kra = k0a_rv(j)%p(i,k) ; tr_ra = tr(m)%t(i,j+1,kra)
1255 wt_b = deep_wt_rv(j)%p(i,k)
1256 tr_av_r = wt_b * tr_rb + (1.0-wt_b) * tr_ra
1259 h_l = hp_lv(j)%p(i,k) ; h_r = hp_rv(j)%p(i,k)
1260 tr_flux = i_maxitt * ((2.0 * h_l * h_r) / (h_l + h_r)) * &
1261 khdt_epi_y(i,j) * (tr_av_l - tr_av_r)
1262 tr_flux_3d(i,j,k) = tr_flux
1264 if (deep_wt_lv(j)%p(i,k) < 1.0)
then
1266 wt_b = deep_wt_lv(j)%p(i,k) ; wt_a = 1.0 - wt_b
1267 vol = hp_lv(j)%p(i,k) * g%areaT(i,j)
1271 if (tr_flux > 0.0)
then
1272 if (tr_la < tr_lb)
then ;
if (vol * (tr_la-tr_min_face) < tr_flux) &
1273 tr_adj_vert = -wt_a * min(tr_flux - vol * (tr_la-tr_min_face), &
1274 (vol*wt_b) * (tr_lb - tr_la))
1275 else ;
if (vol*(tr_lb-tr_min_face) < tr_flux) &
1276 tr_adj_vert = wt_b * min(tr_flux - vol * (tr_lb-tr_min_face), &
1277 (vol*wt_a) * (tr_la - tr_lb))
1279 elseif (tr_flux < 0.0)
then
1280 if (tr_la > tr_lb)
then ;
if (vol * (tr_max_face-tr_la) < -tr_flux) &
1281 tr_adj_vert = wt_a * min(-tr_flux - vol * (tr_max_face-tr_la), &
1282 (vol*wt_b) * (tr_la - tr_lb))
1283 else ;
if (vol*(tr_max_face-tr_lb) < -tr_flux) &
1284 tr_adj_vert = -wt_b * min(-tr_flux - vol * (tr_max_face-tr_lb), &
1285 (vol*wt_a)*(tr_lb - tr_la))
1288 tr_adj_vert_l(i,j,k) = tr_adj_vert
1291 if (deep_wt_rv(j)%p(i,k) < 1.0)
then
1293 wt_b = deep_wt_rv(j)%p(i,k) ; wt_a = 1.0 - wt_b
1294 vol = hp_rv(j)%p(i,k) * g%areaT(i,j+1)
1298 if (tr_flux < 0.0)
then
1299 if (tr_ra < tr_rb)
then ;
if (vol * (tr_ra-tr_min_face) < -tr_flux) &
1300 tr_adj_vert = -wt_a * min(-tr_flux - vol * (tr_ra-tr_min_face), &
1301 (vol*wt_b) * (tr_rb - tr_ra))
1302 else ;
if (vol*(tr_rb-tr_min_face) < (-tr_flux)) &
1303 tr_adj_vert = wt_b * min(-tr_flux - vol * (tr_rb-tr_min_face), &
1304 (vol*wt_a) * (tr_ra - tr_rb))
1306 elseif (tr_flux > 0.0)
then
1307 if (tr_ra > tr_rb)
then ;
if (vol * (tr_max_face-tr_ra) < tr_flux) &
1308 tr_adj_vert = wt_a * min(tr_flux - vol * (tr_max_face-tr_ra), &
1309 (vol*wt_b) * (tr_ra - tr_rb))
1310 else ;
if (vol*(tr_max_face-tr_rb) < tr_flux) &
1311 tr_adj_vert = -wt_b * min(tr_flux - vol * (tr_max_face-tr_rb), &
1312 (vol*wt_a)*(tr_rb - tr_ra))
1315 tr_adj_vert_r(i,j,k) = tr_adj_vert
1317 if (
associated(tr(m)%df2d_y)) &
1318 tr(m)%df2d_y(i,j) = tr(m)%df2d_y(i,j) + tr_flux * idt
1320 endif ;
enddo ;
enddo
1325 do i=is,ie ;
do j=js-1,je ;
if (g%mask2dCv(i,j) > 0.5)
then
1327 klb = k0b_lv(j)%p(i,k); krb = k0b_rv(j)%p(i,k)
1328 if (deep_wt_lv(j)%p(i,k) >= 1.0)
then
1329 tr_flux_conv(i,j,klb) = tr_flux_conv(i,j,klb) - tr_flux_3d(i,j,k)
1331 kla = k0a_lv(j)%p(i,k)
1332 wt_b = deep_wt_lv(j)%p(i,k) ; wt_a = 1.0 - wt_b
1333 tr_flux_conv(i,j,kla) = tr_flux_conv(i,j,kla) - (wt_a*tr_flux_3d(i,j,k) + tr_adj_vert_l(i,j,k))
1334 tr_flux_conv(i,j,klb) = tr_flux_conv(i,j,klb) - (wt_b*tr_flux_3d(i,j,k) - tr_adj_vert_l(i,j,k))
1336 if (deep_wt_rv(j)%p(i,k) >= 1.0)
then
1337 tr_flux_conv(i,j+1,krb) = tr_flux_conv(i,j+1,krb) + tr_flux_3d(i,j,k)
1339 kra = k0a_rv(j)%p(i,k)
1340 wt_b = deep_wt_rv(j)%p(i,k) ; wt_a = 1.0 - wt_b
1341 tr_flux_conv(i,j+1,kra) = tr_flux_conv(i,j+1,kra) + &
1342 (wt_a*tr_flux_3d(i,j,k) - tr_adj_vert_r(i,j,k))
1343 tr_flux_conv(i,j+1,krb) = tr_flux_conv(i,j+1,krb) + &
1344 (wt_b*tr_flux_3d(i,j,k) + tr_adj_vert_r(i,j,k))
1347 endif ;
enddo ;
enddo
1349 do k=1,pemax_krho ;
do j=js,je ;
do i=is,ie
1350 if ((g%mask2dT(i,j) > 0.5) .and. (h(i,j,k) > 0.0))
then
1351 tr(m)%t(i,j,k) = tr(m)%t(i,j,k) + tr_flux_conv(i,j,k) / &
1352 (h(i,j,k)*g%areaT(i,j))
1353 tr_flux_conv(i,j,k) = 0.0
1355 enddo ;
enddo ;
enddo
1361 deallocate(deep_wt_lu(j)%p) ;
deallocate(deep_wt_ru(j)%p)
1362 deallocate(hp_lu(j)%p) ;
deallocate(hp_ru(j)%p)
1363 deallocate(k0a_lu(j)%p) ;
deallocate(k0a_ru(j)%p)
1364 deallocate(k0b_lu(j)%p) ;
deallocate(k0b_ru(j)%p)
1368 deallocate(deep_wt_lv(j)%p) ;
deallocate(deep_wt_rv(j)%p)
1369 deallocate(hp_lv(j)%p) ;
deallocate(hp_rv(j)%p)
1370 deallocate(k0a_lv(j)%p) ;
deallocate(k0a_rv(j)%p)
1371 deallocate(k0b_lv(j)%p) ;
deallocate(k0b_rv(j)%p)
1374 end subroutine tracer_epipycnal_ml_diff
1378 subroutine tracer_hor_diff_init(Time, G, param_file, diag, EOS, CS)
1379 type(time_type),
target,
intent(in) :: time
1381 type(
diag_ctrl),
target,
intent(inout) :: diag
1382 type(
eos_type),
target,
intent(in) :: eos
1387 #include "version_variable.h"
1388 character(len=40) :: mdl =
"MOM_tracer_hor_diff"
1389 character(len=256) :: mesg
1391 if (
associated(cs))
then
1392 call mom_error(warning,
"tracer_hor_diff_init called with associated control structure.")
1398 cs%show_call_tree = calltree_showquery()
1402 call get_param(param_file, mdl,
"KHTR", cs%KhTr, &
1403 "The background along-isopycnal tracer diffusivity.", &
1404 units=
"m2 s-1", default=0.0)
1405 call get_param(param_file, mdl,
"KHTR_SLOPE_CFF", cs%KhTr_Slope_Cff, &
1406 "The scaling coefficient for along-isopycnal tracer "//&
1407 "diffusivity using a shear-based (Visbeck-like) "//&
1408 "parameterization. A non-zero value enables this param.", &
1409 units=
"nondim", default=0.0)
1410 call get_param(param_file, mdl,
"KHTR_MIN", cs%KhTr_Min, &
1411 "The minimum along-isopycnal tracer diffusivity.", &
1412 units=
"m2 s-1", default=0.0)
1413 call get_param(param_file, mdl,
"KHTR_MAX", cs%KhTr_Max, &
1414 "The maximum along-isopycnal tracer diffusivity.", &
1415 units=
"m2 s-1", default=0.0)
1416 call get_param(param_file, mdl,
"KHTR_PASSIVITY_COEFF", cs%KhTr_passivity_coeff, &
1417 "The coefficient that scales deformation radius over "//&
1418 "grid-spacing in passivity, where passivity is the ratio "//&
1419 "between along isopycnal mixing of tracers to thickness mixing. "//&
1420 "A non-zero value enables this parameterization.", &
1421 units=
"nondim", default=0.0)
1422 call get_param(param_file, mdl,
"KHTR_PASSIVITY_MIN", cs%KhTr_passivity_min, &
1423 "The minimum passivity which is the ratio between "//&
1424 "along isopycnal mixing of tracers to thickness mixing.", &
1425 units=
"nondim", default=0.5)
1426 call get_param(param_file, mdl,
"DIFFUSE_ML_TO_INTERIOR", cs%Diffuse_ML_interior, &
1427 "If true, enable epipycnal mixing between the surface "//&
1428 "boundary layer and the interior.", default=.false.)
1429 call get_param(param_file, mdl,
"CHECK_DIFFUSIVE_CFL", cs%check_diffusive_CFL, &
1430 "If true, use enough iterations the diffusion to ensure "//&
1431 "that the diffusive equivalent of the CFL limit is not "//&
1432 "violated. If false, always use the greater of 1 or "//&
1433 "MAX_TR_DIFFUSION_CFL iteration.", default=.false.)
1434 call get_param(param_file, mdl,
"MAX_TR_DIFFUSION_CFL", cs%max_diff_CFL, &
1435 "If positive, locally limit the along-isopycnal tracer "//&
1436 "diffusivity to keep the diffusive CFL locally at or "//&
1437 "below this value. The number of diffusive iterations "//&
1438 "is often this value or the next greater integer.", &
1439 units=
"nondim", default=-1.0)
1440 cs%ML_KhTR_scale = 1.0
1441 if (cs%Diffuse_ML_interior)
then
1442 call get_param(param_file, mdl,
"ML_KHTR_SCALE", cs%ML_KhTR_scale, &
1443 "With Diffuse_ML_interior, the ratio of the truly "//&
1444 "horizontal diffusivity in the mixed layer to the "//&
1445 "epipycnal diffusivity. The valid range is 0 to 1.", &
1446 units=
"nondim", default=1.0)
1449 cs%use_neutral_diffusion = neutral_diffusion_init(time, g, param_file, diag, eos, cs%neutral_diffusion_CSp)
1450 if (cs%use_neutral_diffusion .and. cs%Diffuse_ML_interior)
call mom_error(fatal,
"MOM_tracer_hor_diff: "// &
1451 "USE_NEUTRAL_DIFFUSION and DIFFUSE_ML_TO_INTERIOR are mutually exclusive!")
1453 call get_param(param_file, mdl,
"DEBUG", cs%debug, default=.false.)
1455 id_clock_diffuse = cpu_clock_id(
'(Ocean diffuse tracer)', grain=clock_module)
1456 id_clock_epimix = cpu_clock_id(
'(Ocean epipycnal diffuse tracer)',grain=clock_module)
1457 id_clock_pass = cpu_clock_id(
'(Ocean tracer halo updates)', grain=clock_routine)
1458 id_clock_sync = cpu_clock_id(
'(Ocean tracer global synch)', grain=clock_routine)
1465 cs%id_KhTr_u = register_diag_field(
'ocean_model',
'KHTR_u', diag%axesCu1, time, &
1466 'Epipycnal tracer diffusivity at zonal faces of tracer cell',
'm2 s-1')
1467 cs%id_KhTr_v = register_diag_field(
'ocean_model',
'KHTR_v', diag%axesCv1, time, &
1468 'Epipycnal tracer diffusivity at meridional faces of tracer cell',
'm2 s-1')
1469 cs%id_KhTr_h = register_diag_field(
'ocean_model',
'KHTR_h', diag%axesT1, time,&
1470 'Epipycnal tracer diffusivity at tracer cell center',
'm2 s-1', &
1471 cmor_field_name=
'diftrelo', &
1472 cmor_standard_name=
'ocean_tracer_epineutral_laplacian_diffusivity', &
1473 cmor_long_name =
'Ocean Tracer Epineutral Laplacian Diffusivity')
1475 cs%id_khdt_x = register_diag_field(
'ocean_model',
'KHDT_x', diag%axesCu1, time, &
1476 'Epipycnal tracer diffusivity operator at zonal faces of tracer cell',
'm2')
1477 cs%id_khdt_y = register_diag_field(
'ocean_model',
'KHDT_y', diag%axesCv1, time, &
1478 'Epipycnal tracer diffusivity operator at meridional faces of tracer cell',
'm2')
1479 if (cs%check_diffusive_CFL)
then
1480 cs%id_CFL = register_diag_field(
'ocean_model',
'CFL_lateral_diff', diag%axesT1, time,&
1481 'Grid CFL number for lateral/neutral tracer diffusion',
'nondim')
1485 end subroutine tracer_hor_diff_init
1487 subroutine tracer_hor_diff_end(CS)
1490 call neutral_diffusion_end(cs%neutral_diffusion_CSp)
1491 if (
associated(cs))
deallocate(cs)
1493 end subroutine tracer_hor_diff_end